proc 文件系统简介
最初开发 /proc 文件系统是为了提供有关系统中进程的信息。但是由于这个文件系统非常有用,因此内核中的很多元素也开始使用它来报告信息,或启用动态运行时配置。
/proc 文件系统包含了一些目录(用作组织信息的方式)和虚拟文件。虚拟文件可以向用户呈现内核中的一些信息,也可以用作一种从用户空间向内核发送信息的手段。实际上我们并不会同时需要实现这两点,但是本文将向您展示如何配置这个文件系统进行输入和输出。
顺便说一下,/proc 文件系统并不是 GNU/Linux 系统中的惟一一个虚拟文件系统。在这种系统上,sysfs 是一个与 /proc 类似的文件系统,但是它的组织更好(从 /proc 中学习了很多教训)。不过 /proc 已经确立了自己的地位,因此即使 sysfs 与 /proc 相比有一些优点,/proc 也依然会存在。还有一个 debugfs 文件系统,不过(顾名思义)它提供的更多是调试接口。debugfs 的一个优点是它将一个值导出给用户空间非常简单(实际上这不过是一个调用而已)。
内核模块简介
可加载内核模块(LKM )是用来展示 /proc 文件系统的一种简单方法,这是因为这是一种用来动态地向 Linux 内核添加或删除代码的新方法。LKM 也是 Linux 内核中为设备驱动程序和文件系统使用的一种流行机制。
如果您曾经重新编译过 Linux 内核,就可能会发现在内核的配置过程中,有很多设备驱动程序和其他内核元素都被编译成了模块。如果一个驱动程序被直接编译到了内核中,那么即使这个驱动程 序没有运行,它的代码和静态数据也会占据一部分空间。但是如果这个驱动程序被编译成一个模块,就只有在需要内存并将其加载到内核时才会真正占用内存空间。 有趣的是,对于 LKM 来说,我们不会注意到有什么性能方面的差异,因此这对于创建一个适应于自己环境的内核来说是一种功能强大的手段,这样可以根据可用硬件和连接的设备来加载 对应的模块。
内核程序员可以使用的标准 API ,LKM 程序员也可以使用。LKM 甚至可以导出内核使用的新变量和函数。有关 API 的完整介绍已经超出了本文的范围,因此我们在这里只是简单地介绍后面在展示一个更有用的 LKM 时所使用的几个元素。
一篇好文章:
http://www.ibm.com/developerworks/cn/linux/l-proc.html
proc 相关函数和结构介绍:
1、 create_proc_entry 创建proc 文件
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);
name: 要创建的文件名称;
mode: 该文件的保护掩码;
parent: 确定文件所在目录,如果置NULL ,则位置为/proc 下。
2、 proc_mkdir 创建目录
/* 该函数在父目录parent 下创建一个目录name* */
struct proc_dir_entry * proc_mkdir (const char *name,struct proc_dir_entry *parent);
@name : 要创建的目录名
@parent : 这个目录的父目录
3、 Proc 路径快捷变量
proc_dir_entry 在文件系统中的位置
proc_root_fs /proc
proc_net /proc/net
proc_bus /proc/bus
proc_root_driver /proc/driver
4、 remove_proc_entry 删除文件或目录
/* 这个函数从proc 文件系统中删除一个文件或目录。
* 注意:1 。是通过参数name ,而不是通过创建时返回的指针来删除的。
* 2 。该函数不会递归删除目录下的文件。
* 3 。data 变量保存了分配的内存,要先释放对应内存,再删除该文件。
* */
void remove_proc_entry (const char *name,struct proc_dir_entry *parent);
@name : 要删除的文件或目录名
@parent : 所在的父目录
5、 create_proc_read_entry 创建只读proc 文件
struct proc_dir_entry * create_proc_read_entry (const char
*name,mode_t mode,struct proc_dir_entry *parent,read_proc_t*
read_proc,void *data);
@name : 要创建的文件名
@mode : 要创建的文件的属性 默认0755
@parent : 这个文件的父目录
@read_proc : 当用户读这个文件时,内核调用的函数
@data : 传给read_proc 的参数
6、 Read_func 读函数
int read_func (char *buffer,char **stat,off_t off,int count,int *peof,void *data);
@buffer : 把要返回给用户的信息写在buffer 里,最大不超过PAGE_SIZE (一般4K )
@stat : 一般不使用
@off :buffer 的偏移量
@count : 用户要取的字节数
@peof : 读到文件尾时,把peof 指向的位置置1
@data : 被多个proc 文件定义为读时,通过data 传递参数
注意:返回值必须是sprintf 返回的长度值,如果返回0 在读取的时候会读不到结果。
7 、写函数write_func
/* 该函数最多从buffer 中读取count 个字节的数据。
* 注意:buffer 地址在用户空间,需要先用copy_from_user() 把这些数据拷贝到内核中。* */
int write_func (struct file *file,const char *buffer,unsigned long count,void *data);
@file : 该proc 文件对应的file 结构,一般忽略。
@buffer : 待写的数据所在的位置
@count : 待写数据的大小
@data : 同read_func
注意:返回值应该是实际写入的字符串长度。
文件gx_proc.c
Makefile文件: