proc文件系统读取

本文介绍了在Linux内核4.4(Ubuntu 16.04)下如何操作proc文件系统,包括使用proc_mkdir创建目录,create_proc_entry创建文件,以及read_proc和write_proc函数在内核中实现proc文件的读写操作。通过注册proc文件并实现这两个函数,可以在用户态与内核进行交互。
摘要由CSDN通过智能技术生成

Proc文件系统读取

在以前的版本:(copy 学长的)

在一般的情况下,需要以下函数:

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);

void remove_proc_entry(const char *name, struct proc_dir_entry *parent);

函数 proc_mkdir用于在proc文件系统下创建文件夹, proc_mkdir的第一个参数是要创建的目录的名字,第二个参数是指向父目录结构的指针。需要注意一下几点:

  1. 创建过程没有对于名字的检查,完全可以调用proc_mkdir 创建出一堆同样名字的文件(检查一下会死啊!)

  2. 其实名字可以包含路径,例如“dev/new_proc”, 如果存在dev目录,函数会在dev目录下创建new_proc目录。

  3. 如果第二个参数是NULL,会在根目录也就是/proc/目录下创建目录

函数的返回值就是 新创建目录对应的proc_dir_entry, 保存这个就可以用来在此目录下创建文件啦,其实,即使不保存,利用上面介绍的第二点性质也可以在目录下创建文件,而且删除目录只用知道路径就可以了~

函数create_proc_entry用来创建文件,mode 参数如果为NULL的话默认的文件访问权限是 755,其他的参数与proc_mkdir 类似

函数remove_proc_entry用来删除创建的目录或者文件,有意思的是,这个函数只需要知道名字和父目录就可以删除了。

需要了解下proc_dir_entry 的结构了

struct proc_dir_entry {
    unsigned int low_ino;
    unsigned short namelen;
    const char *name;
    mode_t mode;
    nlink_t nlink;
    uid_t uid;
    gid_t gid;
    loff_t size;
    struct inode_operations * proc_iops;
    const struct file_operations * proc_fops;
    get_info_t *get_info;
    struct module *owner;
    struct proc_dir_entry *next, *parent, *subdir;
    void *data;
    read_proc_t *read_proc;
    write_proc_t *write_proc;
    atomic_t count;     /* use count */
    int deleted;        /* delete flag */
    void *set;
};

其他的参数可以忽略,这里需要注意的是两个成员变量:

read_proc 和 write_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);

对proc文件的读写操作,最终将转化为对read_proc和write_proc的调用。

看到这里明白了吧,只要在内核里注册proc文件,实现read_proc 和write_proc函数,然后设置proc_dir_entry对应成员变量的值,在用户态进行读写就可以和内核交互了

解释这两个函数的参数:

对于read_proc_t

  1. 第一个参数:为啥叫page?答案就是如果对proc文件调用读操作,内核会分配一个页大小的缓冲区。如何输出大于一个页的数据呢,这得依赖于第二个和第三个参数了。

    为了理解第二三个参数,回忆下与文件操作相关的系统调用:

int open(const char *pathname, int flags);
off_t lseek(int fildes, off_t offset, int whence);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

​ 对于proc文件,一次read操作最多只能读取一个page的数据,如果需要读取大于一个页的数据需要保存read的返回 值,然后使用lseek设定offset,然后再次调用read。回到参数的说明:

  1. start和off参数:off对应于lseek里面的offset(lseek whence为SEEK_END,offset为负 的情况下,传进来的off为零,具体原因待考古)。

    如果不设置*start的值,off的取值只能在[0, count - 1]之间,且能够读取的数据大小为:count - off。可以理解系统拷贝了 [page + off, page+count - 1]之间的数据到用户的buffer里。如果off的取值超出范围,read将读不到数据。

    如果设置了*start的值,系统认为*start指向的地址就是off指定的地址,off的值会被忽略&

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值