linux内核解析-proc和sysfs虚拟文件系统

1,512 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

proc和sys目录为linux系统中虚拟文件系统,

sys为系统设备,驱动,总线的信息。

proc为系统将进程等信息显示到用户空间。

这两个虚拟文件系统具体不做介绍,请自行取linux下查看。

proc_1.png

proc_2.png

3.1 内核 seq_file 机制

    普通的文件没有一定的组织结构,文件可以从任意位置开始读写。有一种文件与普通文件不同,它包含一系列的记录,而这些记录按照相同的格式来组织,这种文件称为顺序文件,sqe_file是专门用来处理顺序文件的接口。

//seq_file提供常用接口:
int seq_open(struct file *, const struct seq_operations *);
ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
loff_t seq_lseek(struct file *, loff_t, int);
int seq_release(struct inode *, struct file *);
int seq_write(struct seq_file *seq, const void *data, size_t len);

//示例:一般情况下,只需自己实现.open对应的函数,其他用标准函数seq_read,seq_lseek等。
//具体看 single_open()函数介绍。
static const struct file_operations md_seq_fops = {
    .owner        = THIS_MODULE,
    .open           = md_seq_open,
    .read           = seq_read,
    .llseek         = seq_lseek,
    .release    = seq_release,
    .poll        = mdstat_poll,
};

以上函数可以直接赋值给file_operations文件操作结构的成员。seq_file结构通常保存在file结构的private_data中。

seq_open(): 参数sqe_operations结构是seq_file机制中需要实现的操作函数,需要用户自己去实现。

struct seq_operations {
    void * (*start) (struct seq_file *m, loff_t *pos);
    void (*stop) (struct seq_file *m, void *v);
    void * (*next) (struct seq_file *m, void *v, loff_t *pos);
    int (*show) (struct seq_file *m, void *v);
};

//示例:
static const struct seq_operations md_seq_ops = {
    .start  = md_seq_start,
    .next   = md_seq_next,
    .stop   = md_seq_stop,
    .show   = md_seq_show,
};

3.2 single_open

为了更进一步简化内核接口的实现,封装了该函数,这样我们不用实现整个 seq_operations 结构体,驱动开发者只需要传入 show 即可,其他回调都使用内核实现的一个简单版本,它的代码如下所示:

int single_open(struct file *file, int (*show)(struct seq_file *, void *),
        void *data)
{
    struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL_ACCOUNT);
    int res = -ENOMEM;

    if (op) {
        op->start = single_start;
        op->next = single_next;
        op->stop = single_stop;
        op->show = show;
        res = seq_open(file, op);
        if (!res)
            ((struct seq_file *)file->private_data)->private = data;
        else
            kfree(op);
    }
    return res;
}



//......省略
//以下为只实现show()函数的版本。
static int seq_file_demo_show(struct seq_file *seq, void *v)
{
    seq_printf(seq, "Hello World\n");
    return 0;
}
//file_operations 结构体的open回调。
static int seq_file_demo_open(struct inode *inode, struct file *file)
{
    return single_open(file, &seq_file_demo_show, NULL);
}