Chinaunix首页 | 论坛 | 博客
  • 博客访问: 327176
  • 博文数量: 161
  • 博客积分: 245
  • 博客等级: 二等列兵
  • 技术积分: 694
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-08 13:19
文章分类

全部博文(161)

文章存档

2016年(3)

2015年(31)

2014年(11)

2013年(107)

2012年(9)

分类: LINUX

2013-04-22 14:47:07

原文地址:proc文件系统分析(一) 作者:datao0907

proc文件系统,是一个处于内存中的文件系统,它用于显示当前进程的状态信息,如:进程处于的状态,文件打开描述符,ps程序就是基于此设计出来的。另外,它还可以用于显示当前系统运行的状态如CPU信息,内存信息,中断信息,网络流量等等。通过它可以配置当前系统所运行的一些参数,一般来说,一个文件只有一个数值,这些值的含义可能如下(Linux 2.6.24版):

1.限制缓存的大小

2.开启或关闭某些功能

3.某些内核参数

但是在/proc/sysfs/文件夹下面的文件却不是由proc接口来实现,它采用的是sysctl机制,procfs支持两种类型的API供内核模块使用:

1.标准的procfs API:只要处理的数据量很小时就可以使用,很小的数据量通常限制在一页大小(i386中为4096个字节)

2.seq_file API:seq_file用于处理读请求,它可以支持多于一页大小的读请求,提供了链表来进行遍历,将所有的元素发送至用户空间。

数据结构定义

proc中的每个文件定义如下:


  1. struct proc_dir_entry{

  2. //与普通文件系统类似

  3. unsigned int low_ino;//索引号

  4. unsigned short namelen;//文件名长度

  5. const char* name;//具体文件名

  6. mode_t mode;//权限及文件类型

  7. nlink_t nlink;//来自子文件夹以及符号链接的数量

  8. uid_t uid;//用户id

  9. gid_t gid;//组id,这两个域值一般置为0,代表为root用户所有

  10. loff_t size;//文件大小,由于proc都是动态产生,长度很难知道,一般为0

  11. const struct inode_operations *proc_iops;//暴露给vfs的操作接口

  12. const struct file_operations *proc_fops;

  13. //subdir指向第一个子文件夹

  14. struct proc_dir_entry *next,*parent,*subdir;//文件的组织情况

  15. void *data;

  16. //向内核进行读写的函数指针,需要用户实现

  17. //原型:typedef int (read_proc_t)(char*page,char**start,off_t off,int count,int eof,void* data)

  18. read_proc_t *read_proc;

  19. //原型:typedef int (write_proc_t)(struct file*file,const char __user *buffer,,off_t off,unsigned long //count,void* data)

  20. write_proc_t *write_proc;

  21. atomic_t count;//该文件被内核模块使用的计数

  22. int pde_users;

  23. spinlock_t pde_unload_lock;

  24. struct completion *pde_unload_completion;

  25. struct list_head pde_openers;

  26. }

上面的__user表明该字段来自用户空间,需要通过copy_from_user进行复制,read,write中的data参数则来自proc_dir_entry中的data域,说明proc中注册的read/write可以被多个proc entry进行调用。

proc的索引节点结构体既要连接到VFS文件下,又要保持属于自己proc的数据,所以索引节点的定义就包含了下面两个部分。

proc的索引节点定义如下:


  1. struct proc_inode{

  2. struct pid *pid;//与进程文件夹相关联的进程

  3. int fd;//进程中的/proc//fd文件的文件描述符

  4. union proc_op op;//用于访问文件的函数指针

  5. struct proc_dir_entry *pde;//与文件表项相关的proc_dir_entry

  6. struct inode vfs_inode;

  7. }

  8. union proc_op{

  9. int (*proc_get_link)(struct inode*,struct dentry**,struct vfsmount* *);

  10. int (*proc_read)(struct task_struct *task,char*page);

  11. }
proc初始化

proc文件系统使用之前,需要进行挂载,在挂载期间,内核需要创建,初始化许多类型的文件夹(网络,设备等等),由于与内核,体系结构相关,初始化就存在一些#ifdef的编译选项,它也是通过模块来进行安装进入内核中,代码如下:


  1. fs/proc/root.c

  2. void __init proc_root_init(void)

  3. {

  4. //创建一个proc_inode对象的slab缓存,以加快创建,销毁proc内存节点速度

  5. int err = proc_init_inodecache();

  6. if(err)

  7. return;

  8. //将文件系统注册

  9. err = register_filesystem(&proc_fs_type);

  10. if(err) return;

  11. //注册文件系统之后,就进行挂载,它返回一个vfsmount的实例,保持在全局变量proc_mnt中

  12. //kern_mount_data实际调用函数do_kern_mount

  13. proc_mnt = kern_mount_data(&proc_fs_type,&init_pid_ns);

  14. err = PTR_ERR(proc_mt);

  15. if(IS_ERR(proc_mnt)){

  16. unregister_filesystem(&proc_fs_type);

  17. return;

  18. }

  19. //下面就是产生/proc中的各种文件夹

  20. proc_misc_init();

  21. proc_net_init();

  22. proc_root_fs = proc_mkdir(“fs”,NULL);

  23. proc_root_driver = proc_mkdir(“driver”,NULL);

  24. proc_mkdir(“fs/nfsd”,NULL);

  25. proc_bus = proc_mkdir(“bus”,NULL);

  26. //这个机制有些特别system control mechanism,当一个新的sysctl定义,pro_sys_root就会产生新///的文件

  27. proc_sys_init();

  28. }

proc_misc_init生成/proc main文件夹中的各种文件,它通过特定的程序来读取内核数据结构,这些程序主要如下:

loadavg(loadavg_read_proc):读取系统负载的信息

uptime(uptime_read_proc):

meminfo(meminfo_read_proc):读取内存方面的信息

version(version_read_proc):内核版本信息

….......

对上面的信息进行建立每一个文件,上面的每一个都是只读的,通过调用create_proc_read_entry()

函数实现,其中注册了get_info调用的函数指针。 如meminfo_read_proc函数


  1. static int version_read_proc(char*page,char**start,off_t off,int count,int *eof,void *data)

  2. {

  3. int len;

  4. //转换为指定的格式,写入用户空间

  5. len = sprintf(page,PAGE_SIZE,linux_proc_banner,utsname()->sysname,utsname()->release

  6. ,utsname()->version);

  7. //返回写入的数据长度,主要是判断数据是否在一页中

  8. return proc_calc_metries(page,start,off,count,eof,len);

  9. }
其中的linux_proc_banner定义如下:
  1. const char linux_banner[]=%s version %s ”

  2. (” LINUX_COMPILE_BY “@” LINUX_COMPILE_HOST “)

  3. (” LINUX_COMPILER “) %s\n”;

proc_misc_init返回后,就是系统的不同模块夹进行初始化各自文件夹,每个模块的proc_dir_entry的子目录都设置为全局变量。


阅读(744) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~