本文共 2944 字,大约阅读时间需要 9 分钟。
http://blog.csdn.net/shallnet/article/details/17734619
【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】
在 Linux 系统中,/proc 文件系统十分有用,它被用于内核向用户导出信息。/proc 文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在 Linux 内核空间和用户空间之间进行通信。在/proc 文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,与普通文件不同的是,这些虚拟文件的内容都是动态创建的。Linux 系统的许多命令本身都是通过分析/proc 下的文件来完成,如 ps、top、uptime 和 free等。 在 Linux 设备驱动程序中,驱动工程师自定义/proc 节点以向外界传递信息的方法还是比较常见的。 下列函数用于创建/proc 目录: - struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);
下列函数创建/proc 节点: - struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);
- struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void * data);
结合 create_proc_entry()和 proc_mkdir(),可用于先在/proc 下创建一个目录,而后在该目录下创建一个文件。 可用如下函数删除/proc 节点: - void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
上述函数各返回值的 proc_dir_entry 结构体中包含了/proc 节点的读函数指针(read_proc_t*read_proc)、写函数指针(write_proc_t *write_proc)以及父节点、子节点信息等。/proc 节点的读写函数的类型分别为: - typedef int (read_proc_t)(char *page, char **start, off_t off,int count, int *eof, void *data);
- typedef int (write_proc_t)(struct file *file, const char __user *buffer,unsigned long count, void *data);
这两函数需要我们来实现。 读函数中 page 指针指向用于写入数据的缓冲区,start 用于返回实际的数据写到内存页的位置,eof 是用于返回读结束标志,offset 是读的偏移,count 是要读的数据长度。start 参数比较复杂,对于/proc 只包含简单数据的情况,通常不需要在读函数中设置*start,意味着内核将认为数据保存在内存页偏移 0 的地方。如果将*start 设置为非 0 值,意味着内核将认为*start 指向的数据是 offset 偏移处的数据。写函数与 file_operations 中的 write()成员类似,需要一次从用户缓冲区到内存空间的复制过程。 下面给一个示例,该示例只是简单的在/proc目录下创建一个文件夹和文件,用户可以在用户态向该文件写入文件,并读出文件内容。 - #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/proc_fs.h>
- #include <asm/uaccess.h>
-
- #define USER_ROOT_DIR "slndir"
- #define USER_ENTRY "slnfile"
-
- struct proc_dir_entry *root_dir, *entry;
- char kbuff[1024];
-
- static int proc_write(struct file *filep, const char __user *buffer,
- unsigned long len, void *data)
- {
- if (copy_from_user(kbuff, buffer, len)) {
- return -1;
- }
-
- kbuff[len] = '\0';
- return len;
- }
-
- static int proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
- {
- int len;
-
- len = sprintf(page, "%s", kbuff);
-
- return len;
- }
-
- static int __init sln_init(void)
- {
- printk("Hello, %s\n", __func__);
-
- root_dir = proc_mkdir(USER_ROOT_DIR, NULL);
- if (NULL == root_dir) {
- printk("proc_mkdir create dir %s failed!\n", USER_ROOT_DIR);
- return -1;
- }
-
- entry = create_proc_entry(USER_ENTRY, 0666, root_dir);
- if (NULL == entry) {
- printk("create_proc_entry create entry %s failed\n", USER_ENTRY);
- goto err;
- }
-
- entry->read_proc = proc_read;
- entry->write_proc = proc_write;
- return 0;
-
- err:
- remove_proc_entry(USER_ROOT_DIR, NULL);
- return -1;
- }
-
- static void __exit sln_exit(void)
- {
- printk("Bye, %s\n", __func__);
-
- remove_proc_entry(USER_ENTRY, root_dir);
- remove_proc_entry(USER_ROOT_DIR, NULL);
- }
-
- module_init(sln_init);
- module_exit(sln_exit);
-
- MODULE_LICENSE("GPL");