Introduction to "procfs"
procfs (or
the proc filesystem) is a special filesystem in UNIX-like operating
systems that presents information about processes and
other system information in a hierarchical file-like structure,
providing a more convenient and standardized method for dynamically accessing process data held in the kernel than traditional tracing methods
or direct access tokernel memory.
Typically, it is mapped to a mount
point named /proc
at
boot time. The proc file system acts as an interface to internal data structures in the kernel. It can be used to obtain information about the system and to change certain kernel parameters at runtime (sysctl).
-------------------------------------------------------------------------------------------------------------------------------------------------------
beginners with ‘proc’ 常常会疑惑,proc是个什么东东?上述蓝色强调的部分就很深刻的讲明白了proc是个什么东东。
procfs 是用来提供一种更为便捷,便准的方式,去动态的在内核中读取进程相关数据信息,而这种数据获取方式与传统的直接trace跟踪获取不同.
procfs 前面之所以有proc这个部分,就是因为process。procfs的目的就是为了获取process相关数据信息的!不然你去看/proc/下面那么多数字是干嘛的?那是PID!
假设我们对进程2802感兴趣,我们能查看关于这个进程的什么信息呢?
去目录/proc/2802/ 下面自己看.
比方说查看文件状态我们可以
cat /proc/2802/status
嘿嘿,恰巧,这进程和我打开的chrome浏览器有关系 ,我们可以知道,这个进程当前正在休眠...然后所在的group ID是2802, parent PID是2801等等信息
到这里,大概就有个印象了,“哦~ 原来 proc是用来查看内核数据信息的啊”
proc不完全和进程有关系,proc/目录下非目录的白色部分,例如 modules就是和模块有关的,它记录了当前内核module的名称,而这与具体的某一进程无关.
所以,和wiki说的一样:
The proc file system acts as an interface to internal data structures in the kernel. It can be used to obtain information about the system.
而提到proc不得不讲seq_file,我尝试去单独撇开seq_file,单独给proc写一个demo,但是发现新的内核中(3.13),已经没有create_proc_entry的接口了,proc的所有接口已经完全过渡到了有seq_file参与。
So, It‘s time to talk about seq_file.
问题来了,为什么会有seq_file?
它是作为一种对proc的补充存在的,单独的proc方法有缺陷!———一次只能读 one page size of memory.
It may sound complicated, but, in fact, the process is quite simple. We’ll step through the creation of a /proc file in the scull driver to show how it is done.
不会很麻烦,这里我给出一个简单的demo,然后结合demo进行讲解:
/*********************************************************** code writer : EOF code date : 2014.09.01 code file : proc_demo.c e-mail : [email protected] code purpose: This code is programmed for how to create a proc-entry in procfs. If there is something wrong with my code, please touch me by e-mail. Thank you. ************************************************************/ #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/fs.h> #include <linux/proc_fs.h> /* for procfs */ #include <linux/seq_file.h> #include <linux/types.h> #define PROC_NAME "proc_demo" MODULE_AUTHOR("Jason Leaster"); MODULE_LICENSE("Dual BSD/GPL"); static int proc_demo_seq_show(struct seq_file* sfile,void* v) { int tmp = 0; for(tmp = 0; tmp < 10;tmp++) { seq_printf(sfile,"Hello world!\n"); } return 0; } static void* proc_demo_seq_start(struct seq_file* sfile,loff_t *pos) { return NULL; } static void proc_demo_seq_stop(struct seq_file* sfile,void* v) { /* Nothing to be done. */ } static void* proc_demo_seq_next(struct seq_file* sfile,void* v,loff_t* pos) { return NULL; } static struct seq_operations proc_demo_ops = { .start = proc_demo_seq_start, .next = proc_demo_seq_next, .stop = proc_demo_seq_stop, .show = proc_demo_seq_show, }; static int proc_demo_open(struct inode* inode, struct file* filp) { return single_open(filp,&proc_demo_seq_show,NULL); } struct file_operations proc_demo_fops = { .owner = THIS_MODULE, .open = proc_demo_open, .read = seq_read, .release= seq_release, }; int proc_demo_init(void) { struct proc_dir_entry * entry = NULL; entry = proc_create(PROC_NAME,0,NULL,&proc_demo_fops); if(!entry) { printk(KERN_ALERT "line:%d proc_create failed!",__LINE__); } return 0; } void proc_demo_exit(void) { /* ** The second parameter of 'remove_proc_entry()' is ** a pointer which point to parent directory.We create our ** proc-entry-point in /proc/, so we pass NULL into it. */ remove_proc_entry(PROC_NAME,NULL); } module_init(proc_demo_init); module_exit(proc_demo_exit);
上面给出了创建proc文件系统入口的demo, 它相当于一个框架。我这里的数据读取操作被我替换为简单的向外输出“hello world”,至于不同的应用,对数据进行处理输出即可。
在proc_demo_open()里面我用了single_open(),这里还可以用seq_open。
载入模块后,将在/proc/目录下创建一个叫做 “proc_demo”的入口项,可以用cat 读它!
结合这个最简单的demo,对创建proc入口项进行讲解
The first step, inevitably, is the inclusion of <linux/seq_file.h>. Then you must create four iterator methods, called
start, next, stop, and
show.
The start method is always called first. The prototype for this function is:
void *start(struct seq_file *sfile, loff_t *pos);
The sfile argument can almost always be ignored. pos is an integer position indicating where the reading should start.
star的作用就是定位从那个位置开始seq_file的读操作(后面的show),至于参数sfile不必去管它.
我们这里没有什么特殊偏置操作不必管它,reader可以看scull的实现,然后去看看scull里面对于proc的操作
然后特别注意
start, next, stop, and show.
这四个函数的返回值是不一样的,入口参数也不完全相同。写程序的时候一定注意
struct seq_operations { void * (*start) (struct seq_file *m, loff_t *pos); void (*stop) (struct seq_file *m, void *v); void * (*next) (struct seq_file *m, void *v, loff_t *pos); int (*show) (struct seq_file *m, void *v); };
参考文献:
1: <在
Linux 下用户空间与内核空间数据交换的方式,第 2 部分: procfs、seq_file、debugfs和relayfs>
燚
杨 ([email protected]),
计算机科学硕士
2:proc file system --- wikipedia
3: Driver porting: The seq_file interface [Posted
February 10, 2003 by corbet]