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

开发平台: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高速缓存 

  1. /* linux-2.6.38.8/fs/proc/inode.c */  
  2. void __init proc_init_inodecache(void)  
  3. {  
  4.     proc_inode_cachep = kmem_cache_create("proc_inode_cache",  
  5.                          sizeof(struct proc_inode),  
  6.                          0, (SLAB_RECLAIM_ACCOUNT|  
  7.                         SLAB_MEM_SPREAD|SLAB_PANIC),  
  8.                          init_once);  
  9. }  
/* 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中通过以下命令可查看到此高速缓存相关的信息。 

  1. $ sudo cat /proc/slabinfo | grep "proc_inode_cache"  
  2. proc_inode_cache     310    310    384   10    1 : tunables    0    0    0 : slabdata     31     31      0  
$ 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文件系统的注册和挂载 

  1. /* linux-2.6.38.8/fs/proc/root.c */  
  2.     err = register_filesystem(&proc_fs_type);  
  3.     if (err)  
  4.         return;  
  5.     proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns);  
  6.     if (IS_ERR(proc_mnt)) {  
  7.         unregister_filesystem(&proc_fs_type);  
  8.         return;  
  9.     }  
  10.   
  11.     init_pid_ns.proc_mnt = proc_mnt;  
/* 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)、创建符号链接文件的函数 

  1. /* linux-2.6.38.8/fs/proc/generic.c */  
  2. struct proc_dir_entry *proc_symlink(const char *name,  
  3.         struct proc_dir_entry *parent, const char *dest)  
  4. {  
  5.     struct proc_dir_entry *ent;  
  6.   
  7.     ent = __proc_create(&parent, name,  
  8.               (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);  
  9.   
  10.     if (ent) {  
  11.         ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);  
  12.         if (ent->data) {  
  13.             strcpy((char*)ent->data,dest);  
  14.             if (proc_register(parent, ent) < 0) {  
  15.                 kfree(ent->data);  
  16.                 kfree(ent);  
  17.                 ent = NULL;  
  18.             }  
  19.         } else {  
  20.             kfree(ent);  
  21.             ent = NULL;  
  22.         }  
  23.     }  
  24.     return ent;  
  25. }  
/* 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文件的。 

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

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

  1. /* linux-2.6.38.8/fs/proc/proc_net.c */  
  2. int __init proc_net_init(void)  
  3. {  
  4.     proc_symlink("net", NULL, "self/net");  
  5.   
  6.     return register_pernet_subsys(&proc_net_ns_ops);  
  7. }  
/* 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)、创建目录的函数 

  1. /* linux-2.6.38.8/fs/proc/generic.c */  
  2. struct proc_dir_entry *proc_mkdir(const char *name,  
  3.         struct proc_dir_entry *parent)  
  4. {  
  5.     return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);  
  6. }  
/* 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目录树 

  1. /* linux-2.6.38.8/fs/proc/proc_tty.c */  
  2. void __init proc_tty_init(void)  
  3. {  
  4.     if (!proc_mkdir("tty", NULL))  
  5.         return;  
  6.     proc_tty_ldisc = proc_mkdir("tty/ldisc", NULL);  
  7.     /* 
  8.      * /proc/tty/driver/serial reveals the exact character counts for 
  9.      * serial links which is just too easy to abuse for inferring 
  10.      * password lengths and inter-keystroke timings during password 
  11.      * entry. 
  12.      */  
  13.     proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);  
  14.     proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);  
  15.     proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);  
  16. }  
/* 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);
}
  1. /* linux-2.6.38.8/include/linux/proc_fs.h */  
  2. static inline struct proc_dir_entry *proc_create(const char *name, mode_t mode,  
  3.     struct proc_dir_entry *parent, const struct file_operations *proc_fops)  
  4. {  
  5.     return proc_create_data(name, mode, parent, proc_fops, NULL);  
  6. }  
/* 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目录的操作函数 

  1. /* linux-2.6.38.8/fs/proc/proc_sysctl.c */  
  2. int __init proc_sys_init(void)  
  3. {  
  4.     struct proc_dir_entry *proc_sys_root;  
  5.   
  6.     proc_sys_root = proc_mkdir("sys", NULL);  
  7.     proc_sys_root->proc_iops = &proc_sys_dir_operations;  
  8.     proc_sys_root->proc_fops = &proc_sys_dir_file_operations;  
  9.     proc_sys_root->nlink = 0;  
  10.     return 0;  
  11. }  
/* 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目录树 

  1. /* linux-2.6.38.8/fs/proc/proc_devtree.c */  
  2. void __init proc_device_tree_init(void)  
  3. {  
  4.     struct device_node *root;  
  5.   
  6.     proc_device_tree = proc_mkdir("device-tree", NULL);  
  7.     if (proc_device_tree == NULL)  
  8.         return;  
  9.     root = of_find_node_by_path("/");  
  10.     if (root == NULL) {  
  11.         pr_debug("/proc/device-tree: can't find root\n");  
  12.         return;  
  13.     }  
  14.     proc_device_tree_add_node(root, proc_device_tree);  
  15.     of_node_put(root);  
  16. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值