seq_file接口

来源:互联网 发布:淘宝助理4.6版下载 编辑:程序博客网 时间:2024/04/20 13:55
 

下面是网上的一个测试程序

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/module.h>

#include <linux/proc_fs.h>

#include <linux/seq_file.h>

MODULE_DESCRIPTION("test proc");

MODULE_AUTHOR("root ");

MODULE_LICENSE("GPL");

/* Private Data structure */

struct _mydrv_struct

{

    /* ... */

    struct list_head list; /* Link to the next node */

    char info[10];          /* Info to pass via the procfs file */

    /* ... */

};

static LIST_HEAD(mydrv_list); /* List Head */

/* start() method */

static void *

   mydrv_seq_start(struct seq_file *seq, loff_t *pos)

{
   seq_printf(seq, "START\n");

struct _mydrv_struct *p;

loff_t off = 0;

/* The iterator at the requested offset */

list_for_each_entry(p, &mydrv_list, list) {

   if (*pos == off++) return p;

}

return NULL;

}

/* next() method */

static void *

   mydrv_seq_next(struct seq_file *seq, void *v, loff_t *pos)

{

/* 'v' is a pointer to the iterator returned by start() or

by the previous invocation of next() */

struct list_head *n = ((struct _mydrv_struct *)v)->list.next;

++*pos; /* Advance position */

/* Return the next iterator, which is the next node in the list */
seq_printf(seq, "next\n");

return(n != &mydrv_list) ?

    list_entry(n, struct _mydrv_struct, list) : NULL;

}

/* show() method */

static int

   mydrv_seq_show(struct seq_file *seq, void *v)

{

const struct _mydrv_struct *p = v;

/* Interpret the iterator, 'v' */
seq_printf(seq, "show\n");

seq_printf(seq, p->info);

return 0;

}

/* stop() method */

static void mydrv_seq_stop(struct seq_file *seq, void *v)

{
  seq_printf(seq, "stop\n");

/* No cleanup needed in this example */

}

/* Define iterator operations */

static struct seq_operations mydrv_seq_ops = {

.start = mydrv_seq_start,

.next = mydrv_seq_next,

.stop = mydrv_seq_stop,

.show = mydrv_seq_show,

};

static int

   mydrv_seq_open(struct inode *inode, struct file *file)

{

/* Register the operators */

return seq_open(file, &mydrv_seq_ops);

}

static struct file_operations mydrv_proc_fops = {

.owner   = THIS_MODULE,

.open    = mydrv_seq_open, /* User supplied */

.read    = seq_read,       /* Built-in helper function */

.llseek = seq_lseek,      /* Built-in helper function */

.release = seq_release,    /* Built-in helper funciton */

};

 

static int test_proc_init_module(void)

{

 

int i;

static struct proc_dir_entry *entry = NULL ;

struct _mydrv_struct * mydrv_new;

 

/* Create /proc/readme */

entry = create_proc_entry("readme", S_IWUSR, NULL);

if (entry)

{

   entry->proc_fops = &mydrv_proc_fops;

}

/* Handcraft mydrv_list for testing purpose.

In the real world, device driver logic

maintains the list and populates the 'info' field */

for (i=0;i<5;i++)

{

   mydrv_new = kmalloc(sizeof(struct _mydrv_struct), GFP_ATOMIC);

   sprintf(mydrv_new->info, "Node No: %d\n", i);

   list_add_tail(&mydrv_new->list, &mydrv_list);

}

return 0;

}

static void test_proc_exit_module(void)

{

remove_proc_entry("readme",0);

printk( KERN_DEBUG "Module test_proc exit\n" );

}

module_init(test_proc_init_module);

module_exit(test_proc_exit_module);

Makefile 如下

obj-m := seq_file2.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
 $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
 $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
 rm -rf Module.markers modules.order Module.symvers

 

加载模块运行,

cat  /proc/readme

得到的效果如下:

START
show
Node No: 0
next
show
Node No: 1
next
show
Node No: 2
next
show
Node No: 3
next
show
Node No: 4
next
stop

因此我们可以知道,start 首先被调用它初始化迭代子对象的位置并且返回插入的第一个迭代子对象。

接着调用shou,再next ,show ...... 直到迭代完所有的对象。最后调用stop完成清理工作。

原创粉丝点击