通过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函数所调用,用来完成注册、挂载文件系统以及创建必要的目录和符号链接文件等工作。

 

通过proc文件系统输出必要的Linux内核信息(上)_第1张图片

    (1)、创建proc_inode_cache高速缓存 

[cpp] view plain copy print ?
  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. }  

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

[cpp] view plain copy print ?
  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  

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

[cpp] view plain copy print ?
  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;  

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

[cpp] view plain copy print ?
  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. }  

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

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

[cpp] view plain copy print ?
  1. $ cd /proc/  
  2. $ ls -l mounts   
  3. lrwxrwxrwx 1 root root 11 2012-01-13 04:32 mounts -> self/mounts  

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

[cpp] view plain copy print ?
  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. }  

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

    (5)、创建目录的函数 

[cpp] view plain copy print ?
  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. }  

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

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

[cpp] view plain copy print ?
  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. }  
[cpp] view plain copy print ?
  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. }  

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

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

[cpp] view plain copy print ?
  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. }  

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

[cpp] view plain copy print ?
  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. }  

你可能感兴趣的:(通过proc文件系统输出必要的Linux内核信息(上))