现在的位置: 首页 > 综合 > 正文

通过proc文件系统输出必要的Linux内核信息(上)

2013年10月25日 ⁄ 综合 ⁄ 共 3714字 ⁄ 字号 评论关闭

    开发平台:Ubuntu 11.04

    编译器:gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

    内核源码:linux-2.6.38.8.tar.bz2

 

    proc是基于内存的文件系统,用来实现外界与Linux内核的信息交互(通过/proc目录下的各种文件)。

    1、proc文件系统的初始化

    proc文件系统的初始化函数proc_root_init被start_kernel函数所调用,用来完成注册、挂载文件系统以及创建必要的目录和符号链接文件等工作。

 

    (1)、创建proc_inode_cache高速缓存 

/* linux-2.6.38.8/fs/proc/inode.c */
void __init proc_init_inodecache(void)
{
	proc_inode_cachep = kmem_cache_create("proc_inode_cache",
					     sizeof(struct proc_inode),
					     0, (SLAB_RECLAIM_ACCOUNT|
						SLAB_MEM_SPREAD|SLAB_PANIC),
					     init_once);
}

    在Ubuntu 11.04中通过以下命令可查看到此高速缓存相关的信息。 

$ sudo cat /proc/slabinfo | grep "proc_inode_cache"
proc_inode_cache     310    310    384   10    1 : tunables    0    0    0 : slabdata     31     31      0

    (2)、proc文件系统的注册和挂载 

/* linux-2.6.38.8/fs/proc/root.c */
	err = register_filesystem(&proc_fs_type);
	if (err)
		return;
	proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns);
	if (IS_ERR(proc_mnt)) {
		unregister_filesystem(&proc_fs_type);
		return;
	}

	init_pid_ns.proc_mnt = proc_mnt;

    (3)、创建符号链接文件的函数 

/* linux-2.6.38.8/fs/proc/generic.c */
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);

	if (ent) {
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
		if (ent->data) {
			strcpy((char*)ent->data,dest);
			if (proc_register(parent, ent) < 0) {
				kfree(ent->data);
				kfree(ent);
				ent = NULL;
			}
		} else {
			kfree(ent);
			ent = NULL;
		}
	}
	return ent;
}

    proc_symlink函数用于在parent(如果parent为NULL则是在/proc目录下)目录下为dest创建名为name的符号链接文件。

    可在Ubuntu 11.04的/proc目录下查看到mounts文件是链接到self/mounts文件的。 

$ cd /proc/
$ ls -l mounts 
lrwxrwxrwx 1 root root 11 2012-01-13 04:32 mounts -> self/mounts

    (4)、创建net符号链接文件 

/* linux-2.6.38.8/fs/proc/proc_net.c */
int __init proc_net_init(void)
{
	proc_symlink("net", NULL, "self/net");

	return register_pernet_subsys(&proc_net_ns_ops);
}

    register_pernet_subsys函数用来注册网络命名空间。网络命名空间被创建或注销时会分别调用proc_net_ns_ops结构体变量中的初始化函数proc_net_ns_init或退出函数proc_net_ns_exit。

    (5)、创建目录的函数 

/* linux-2.6.38.8/fs/proc/generic.c */
struct proc_dir_entry *proc_mkdir(const char *name,
		struct proc_dir_entry *parent)
{
	return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
}

    proc_mkdir函数用于在parent(parent为NULL时则是在/proc目录下)目录下创建名为name的目录,其实质是参数mode指定为S_IRUGO | S_IXUGO的proc_mkdir_mode函数。

    (6)、初始化/proc/tty目录树 

/* linux-2.6.38.8/fs/proc/proc_tty.c */
void __init proc_tty_init(void)
{
	if (!proc_mkdir("tty", NULL))
		return;
	proc_tty_ldisc = proc_mkdir("tty/ldisc", NULL);
	/*
	 * /proc/tty/driver/serial reveals the exact character counts for
	 * serial links which is just too easy to abuse for inferring
	 * password lengths and inter-keystroke timings during password
	 * entry.
	 */
	proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
	proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
	proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
}
/* linux-2.6.38.8/include/linux/proc_fs.h */
static inline struct proc_dir_entry *proc_create(const char *name, mode_t mode,
	struct proc_dir_entry *parent, const struct file_operations *proc_fops)
{
	return proc_create_data(name, mode, parent, proc_fops, NULL);
}

    proc_create函数用于在parent(当parent为NULL时则是在/proc目录下)目录下创建一个名为name的proc条目,参数proc_fops指的是访问此条目的操作函数,参数mode用于设置此条目的访问权限以及文件类型。

    (7)、初始化/proc/sys目录的操作函数 

/* linux-2.6.38.8/fs/proc/proc_sysctl.c */
int __init proc_sys_init(void)
{
	struct proc_dir_entry *proc_sys_root;

	proc_sys_root = proc_mkdir("sys", NULL);
	proc_sys_root->proc_iops = &proc_sys_dir_operations;
	proc_sys_root->proc_fops = &proc_sys_dir_file_operations;
	proc_sys_root->nlink = 0;
	return 0;
}

    (8)、初始化/proc/drivers-tree目录树 

/* linux-2.6.38.8/fs/proc/proc_devtree.c */
void __init proc_device_tree_init(void)
{
	struct device_node *root;

	proc_device_tree = proc_mkdir("device-tree", NULL);
	if (proc_device_tree == NULL)
		return;
	root = of_find_node_by_path("/");
	if (root == NULL) {
		pr_debug("/proc/device-tree: can't find root\n");
		return;
	}
	proc_device_tree_add_node(root, proc_device_tree);
	of_node_put(root);
}

抱歉!评论已关闭.