Seq_file文件系统实例剖析

Seq_file File System
针对proc文件的不足而诞生了Seq_file。
Seq_file的实现基于proc文件。使用Seq_file,用户必须抽象出一个链接对象,然后可以依次遍历这个链接对象。这个链接对象可以是链表,数组,哈希表等等。
编程接口
Seq_file必须实现四个操作函数:start(), next(), show(), stop()。

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

start():
主要实现初始化工作,在遍历一个链接对象开始时,调用。返回一个链接对象的偏移或者SEQ_START_TOKEN(表征这是所有循环的开始)。出错返回ERR_PTR。
stop():
当所有链接对象遍历结束时调用。主要完成一些清理工作。
next():
用来在遍历中寻找下一个链接对象。返回下一个链接对象或者NULL(遍历结束)。
show():
对遍历对象进行操作的函数。主要是调用seq_printf(), seq_puts()之类的函数,打印出这个对象节点的信息。
下图描述了seq_file函数对一个链表的遍历。

2、重要的数据结构
除了struct seq_operations以外,另一个最重要的数据结构是struct seq_file:
struct seq_file {
        char *buf;
        size_t size;
        size_t from;
        size_t count;
        loff_t index;
        u64 version;
        struct mutex lock;
        const struct seq_operations *op;
        void *private;
};
该结构会在seq_open函数调用中分配,然后作为参数传递给每个seq_file的操作函数。Privat变量可以用来在各个操作函数之间传递参数。

3、Seq_file使用示例:
#include <net/net_namespace.h> /* for use of init_net*/
#include <linux/kernel.h> /* We\'re doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/proc_fs.h> /* Necessary because we use proc fs */
#include <linux/seq_file.h> /* for seq_file */

#define PROC_NAME \"my_seq_proc\"
MODULE_AUTHOR(\"Dreamice:dreamice.jiang@mail.com\");
MODULE_LICENSE(\"GPL\");

static void *my_seq_start(struct seq_file *s, loff_t *pos)
{
        static unsigned long counter = 0;
        printk(KERN_INFO\"Invoke start\\n\");
        /* beginning a new sequence ? */
        if ( *pos == 0 )
        {
                /* yes => return a non null value to begin the sequence */
                printk(KERN_INFO\"pos == 0\\n\");
                return &counter;
        }
        else
        {
                /* no => it\'s the end of the sequence, return end to stop reading */
                *pos = 0;
                printk(KERN_INFO\"pos != 0\\n\");
                return NULL;
        }
}

static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
        unsigned long *tmp_v = (unsigned long *)v;
        printk(KERN_INFO\"Invoke next\\n\");
        (*tmp_v)++;
        (*pos)++;
        return NULL;
}

static void my_seq_stop(struct seq_file *s, void *v)
{
        printk(KERN_INFO\"Invoke stop\\n\");
        /* nothing to do, we use a static value in start() */
}

static int my_seq_show(struct seq_file *s, void *v)
{
        printk(KERN_INFO\"Invoke show\\n\");
        loff_t *spos = (loff_t *) v;
        seq_printf(s, \"%Ld\\n\", *spos);
        return 0;
}

static struct seq_operations my_seq_ops = {
        .start = my_seq_start,
        .next = my_seq_next,
        .stop = my_seq_stop,
        .show = my_seq_show
};

static int my_open(struct inode *inode, struct file *file)
{
        return seq_open(file, &my_seq_ops);
};

static struct file_operations my_file_ops = {
        .owner = THIS_MODULE,
        .open = my_open,
        .read = seq_read,
        .llseek = seq_lseek,
        .release = seq_release
};

int init_module(void)
{
        struct proc_dir_entry *entry;
        entry = create_proc_entry(PROC_NAME, 0, init_net.proc_net);
        if (entry) {
                entry->proc_fops = &my_file_ops;
        }
        printk(KERN_INFO\"Initialze my_seq_proc success!\\n\");
        return 0;
}
/**
* This function is called when the module is unloaded.
*
*/

void cleanup_module(void)
{
        remove_proc_entry(PROC_NAME, init_net.proc_net);
        printk(KERN_INFO\"Remove my_seq_proc success!\\n\");
}



该程序在/proc/net下注册一个my_seq_proc文件。有兴趣的朋友可以测试一下。

总结待续

原文地址:http://blog.chinaunix.net/space.php?uid=7201775&do=blog&id=25898

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值