Board logo

标题: Linux内核中的proc文件系统 [打印本页]

作者: yuyang911220    时间: 2017-4-23 20:14     标题: Linux内核中的proc文件系统

简介
procfs文件系统是内核中的一个特殊文件系统。它是一个虚拟文件系统:  它不是实际的存储设备中的文件,而是存在于内存中。procfs中的文件是用来允许用户空间的程序访问内核中的某些信息(比如进程信息在  /proc/[0-9]+/中),或者用来做调试用途(/proc/ksyms,这个文件列出了已经登记的内核符号,这些符号给出了变量或函数的地址。每行给出一个符号的地址,符号名称以及登记这个符号的模块。程序ksyms、insmod和kmod使用这个文件。它还列出了正在运行的任务数,总任务数和最后分配的PID。)
这个文档描述了内核中procfs文件系统的使用。它以介绍所有和管理文件系统相关的函数开始。在函数介绍后,它还展示了怎么和用户空间通信,和一些小技巧。在文档的最后,还给出了一个完整的例子。
注意/proc/sys中的文件属于sysctl文件,它们不属于procfs文件系统,被另外一套完全不同的api管理。
seq_file
procfs在处理大文件时有点笨拙。为了清理procfs文件系统并且使内核编程简单些,引入了seq_file机制。seq_file机制提供了大量简单的接口去实现大内核虚拟文件。
seq_file机制适用于你利用结构序列去创建一个返回给用户空间的虚拟文件。要使用seq_file机制,你必须创建一个”iterator”对象,这个对象指向这个序列,并且能逐个指向这个序列中的对象,此外还要能输出这个序列中的任一个对象。它听起来复杂,实际上,操作过程相当简单。接下来将用实际的例子展示到底怎么做。
首先,你必须包含头文件<Linux/seq_file.h>。接下来,你必须创建迭代器方法:start, next, stop, and  show。
start方法通常被首先调用。这个方法的函数原型是:
sfile没什么作用,通常被忽略。pos参数是一个整型,表示从哪个位置开始读。关于位置的定义完全取决于函数实现;它不一定要是结果文件中的一个字节位置。  由于seq_file机制通常是利用一个特定的结构序列实现的,所以位置通常是一个指向序列中下一个结构体的指针。在wing驱动中,每一个设备表示序列中的一个结构,所以,入参pos代表g_pstWingDevices数组的索引。因此,在wing驱动中start方法的实现为:
返回值如果不为NULL,代表一个可以被迭代器使用的私有数据。
next函数应该移动迭代器到下一个位置,如果序列中没有数据,返回NULL。这个方法的函数原型为:
这里,参数v代表上一个函数调用(可能是start函数,或者是next函数)返回的迭代器,,  参数pos是文件中的当前位置。next函数应该改变pos的指向,具体是逐步改变还是跳跃改变取决于迭代器的工作机制。next函数在wing驱动中的实现为:
当内核停止了迭代器的工作,它调用stop函数清理现场:
wing驱动没有清理工作要做,所以stop函数为空。
要是seq_file代码在调用start和stop时不执行睡眠或是非原子的操作,那么这种机制将毫无意义。你要保证从start函数调用到stop函数调用是很短暂的。因此,在开始函数中获得一个信号量或者自旋锁是比较安全的做法。要是seq_file其他方法是原子的,整个调用链必须是原子的。
在这些函数调用中,内核调用call函数向内核空间输出特性的信息。这个函数的函数原型是:
这个方法应该创建序列中由指示器v指定项的输出。不能使用printk,而是使用以下这些特定函数:
这个函数是seq_file机制中类似于printf的实现;它使用通常的格式字符串和参数组成输出字符串。你必须把show函数中的seq_file结构体传给这个函数。如果它返回一个非零的值,表示buffer已经填充好,输出被丢出去了。在大多数实现中,都选择忽略返回值。
这两个函数相当于用户层的putc和puts。
这个函数是 seq_puts 的对等体, 除了 s 中的任何也在 esc 中出现的字符以八进制格式打印. esc 的一个通用值是”\t\n\”,  它使内嵌的空格不会搞乱输出和可能搞乱 shell 脚本.
这个函数能够用来输出和给定命令项关联的文件名子. 它在设备驱动中不可能有用;我们是为了完整在此包含它.
wing设备中的show函数例子:
在我的例子中,我将一个ST_Wing_Dev_Type结构体表示为迭代器。
上面就是完整的迭代器操作,wing驱动必须将它们打包到一起好连接到procfs文件系统。首先要做的就是利用它们组成一个seq_operations结构体:
有了这个结构,我们必须创建一个内核能理解的文件实现。我们不使用前面说过的read_proc方法;在使用seq_file时,  最好在一个稍低的级别上连接到procfs。这意味着创建一个file_operations(和字符设备一样的结构),这个结构实现了内核对文件的reads和seeks操作。幸运的是,这个操做很简单。首先创建一个把文件和seq_file方法联接起来的open方法:
调用seq_open函数的时候将文件和上面定义的序列操作关联到一起。open是唯一要我们实现的函数接口,所以我们的file_operations结构体是:
最后我们要在procfs文件系统中创建文件:





欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0