创建一个 proc 文件

创建一个 proc 文件 
根据对 proc 文件的不同使用,内核提供了多种包装函数来创建一个 proc 文件。 
方法一: 
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent) 
这是最直接,包装最少的创建方法。 
参数 name 是要创建的 proc 文件名。mode 是该文件权限值,例如 S_IRUGO,可传入0表示采用系统默认值。
parent 指定该文件的上层 proc 目录项,如果为 NULL,表示创建在 /proc 根目录下。 
create_proc_entry() 完成的任务主要包括:检测 mode 值,分配 proc_dir_entry 结构,注册 proc_dir_entry。 
方法二: 
static inline 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) 

    struct proc_dir_entry *res=create_proc_entry(name,mode,base); 
    if (res) { 
        res->read_proc=read_proc; 
        res->data=data; 
    } 
    return res; 

如果要创建一个只读的 proc 文件,可以采用 create_proc_read_entry() 这个接口。这个接口其实就是给 proc_dir_entry 多赋了两个值,其中 read_proc 是一个函数指针, data 是 read_proc 调用时传给它一个参数。关于 read_proc 函数,接下来会另行分析。 
方法三: 
struct proc_dir_entry *proc_create(const char *name, mode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops) 
如果要创建一个 proc 文件,并且不用 proc_fs 默认提供的 file_operations 的话,可以使用 proc_create() 这个函数,
通过最后一个参数来指定要创建的 proc 文件的 file_operations。 
每个 proc 文件也都会用到 file_operations,在调用 create_proc_entry() 创建 proc 文件时,其中一步是调用 proc_register(),proc_register() 会为 proc_dir_entry 提供一个默认的 file_operations,
而 proc_create() 与 create_proc_entry() 唯一差别就是在调用 proc_register() 前先设置好 proc_dir_entry 的 file_operations,这样在 proc_register() 时就不会设置使用 proc_fs 默认的 file_operations 了。 
proc_fs 默认的 file_operations 定义如下: 
static const struct file_operations proc_file_operations = { 
    .llseek        = proc_file_lseek, 
    .read        = proc_file_read, 
    .write        = proc_file_write, 
}; 
关于这个 proc_file_operations,后面会继续讲到。 
proc_create() 一般在创建使用 seq_file 接口的 proc 文件时会使用。 

创建一个 proc 目录 
创建一个 proc 目录就调用 struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent) 这个函数。
参数name 是目录名,parent 是该目录的上层 proc 目录项,如果为 NULL,表示创建在 /proc 根目录下。 

删除一个 proc 项 
要删除一个 proc 文件或目录就调用 void remove_proc_entry(const char *name, struct proc_dir_entry *parent) 

注意事项
 
proc 项创建时要避免已经存在同名的 proc 项,否则注册时内核会报错(但还是会成功返回那个 proc 项),在删除时有时会删不掉(尤其是 proc 目录)。 
删除一个 proc 目录会把这个目录所有的 proc 文件都删除。 

读 proc 文件
 
proc 文件的读需要自己提供一个 read_proc_t 类型的函数放在 proc_dir_entry 结构中供 proc_file_read() 函数调用。下面是 read_proc_t 类型函数的定义: 
typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data); 
这个函数的定义很复杂,不过当 proc 文件返回的数据量总是小于一个 PAGE_SIZE 时可以简化使用。关于这个函数以及它的那一大串参数我觉得再怎么解释都解释不全,所以还是留给自己去看 proc_file_read() 的代码就明白了。 
写 proc 文件 
proc 文件的写很简单。如果是使用 proc_fs 默认提供的 file_operations 的话,要自己实现一个 write_proc_t 类型的函数放在 proc_dir_entry 结构中供 proc_file_write() 函数调用。write_proc_t 类型函数的定义如下: 
typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data); 
下面是 proc_file_write() 的实现: 
static size_t proc_file_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 

    struct inode *inode = file->f_path.dentry->d_inode; 
    struct proc_dir_entry * dp; 
    dp = PDE(inode); 
    f (!dp->write_proc) 
        return -EIO; 
    /* FIXME: does this routine need ppos? probably... */ 
    return dp->write_proc(file, buffer, count, dp->data); 

可见 proc 文件的写忽略了使用偏移量。 
如果是使用自己提供的 file_operations 的话,那还是要自己实现一个 write 函数赋给 file_operations 的 .write 指针。 
一个例子 

  1: #include <linux/module.h> 
  2: #include <linux/proc_fs.h> 
  3: #include <asm/uaccess.h> 
  4: static struct proc_dir_entry *mydir; 
  5: static struct proc_dir_entry *pfile; 
  6: static char msg[255]; 
  7: static int myproc_read(char *page, char **start, off_t off, int count, int *eof, void *data) 
  8: { 
  9:         int len = strlen(msg); 
 10:         if (off >= len) 
 11:                 return 0; 
 12:         if (count > len - off) 
 13:                 count = len - off; 
 14:         memcpy(page + off, msg + off, count); 
 15:         return off + count; 
 16: } 
 17: static int myproc_write(struct file *file, const char __user *buffer, unsigned long count, void *data) 
 18: { 
 19:         unsigned long count2 = count; 
 20:         if (count2 >= sizeof(msg)) 
 21:                 count2 = sizeof(msg) - 1; 
 22:         if (copy_from_user(msg, buffer, count2)) 
 23:                 return -EFAULT; 
 24:         msg[count2] = '\0'; 
 25:         return count; 
 26: } 
 27: static int __init myproc_init(void) 
 28: { 
 29:         mydir = proc_mkdir("mydir", NULL); 
 30:         if (!mydir) { 
 31:                 printk(KERN_ERR "Can't create /proc/mydir\n"); 
 32:                 return -1; 
 33:         } 
 34:         pfile = create_proc_entry("pool", 0666, mydir); 
 35:         if (!pfile) { 
 36:                 printk(KERN_ERR "Can't create /proc/mydir/pool\n"); 
 37:                 remove_proc_entry("mydir", NULL); 
 38:                 return -1; 
 39:         } 
 40:         pfile->read_proc = myproc_read; 
 41:         pfile->write_proc = myproc_write; 
 42:         return 0; 
 43: } 
 44: static void __exit myproc_exit(void) 
 45: { 
 46:         remove_proc_entry("pool", mydir); 
 47:         remove_proc_entry("mydir", NULL); 
 48: } 
 49: module_init(myproc_init); 
 50: module_exit(myproc_exit);

这个例子创建一个 /proc/mydir/pool,它相当于一个池子,你向它写什么,你读它的时候它就返回什么,当然它的容量是有限的 :)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值