http://blog.csdn.net/shallnet/article/details/17734619
【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】
在 Linux 设备驱动程序中,驱动工程师自定义/proc 节点以向外界传递信息的方法还是比较常见的。
下列函数用于创建/proc 目录:
- struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);
- 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);
可用如下函数删除/proc 节点:
- void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
- 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");