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);
};
seq_file的使用
struct file_operations exam_seq_file_ops = {
.owner   = THIS_MODULE,
.open    = exm_seq_open,
.read    = seq_read,
.llseek  = seq_lseek,
.release = seq_release
};
static int exam_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &exam_seq_ops);
};

struct proc_dir_entry *entry;
            entry = create_proc_entry("exam_seq_file", 0, NULL);
            if (entry)
            entry->proc_fops = &exam_seq_file_ops;


当用户态的程序打开这个对应的proc目录时,open->sysopen->exm_seq_open->seq_open(file,&exam_seq_ops),下面我们主要来看下seq_open函数
int seq_open(struct file *file, const struct seq_operations *op)
{
 struct seq_file *p = file->private_data;

 if (!p) {
  p = kmalloc(sizeof(*p), GFP_KERNEL); 
  if (!p)
   return -ENOMEM;
  file->private_data = p;
 }
 memset(p, 0, sizeof(*p));
 mutex_init(&p->lock);
 p->op = op;

 /*
  * Wrappers around seq_open(e.g. swaps_open) need to be
  * aware of this. If they set f_version themselves, they
  * should call seq_open first and then set f_version.
  */
 file->f_version = 0;

 /* SEQ files support lseek, but not pread/pwrite */
 file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
 return 0;
}
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_read函数
/**
 * seq_read - ->read() method for sequential files.
 * @file: the file to read from
 * @buf: the buffer to read to
 * @size: the maximum number of bytes to read
 * @ppos: the current position in the file
 *
 * Ready-made ->f_op->read()
 */
ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
 struct seq_file *m = (struct seq_file *)file->private_data;
 /* grab buffer if we didn't have one */
 if (!m->buf) {
  m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
  if (!m->buf)
   goto Enomem;
 }
 p = m->op->start(m, &pos);
 while (1) {
  err = m->op->show(m, p);

   p = m->op->next(m, p, &pos);

  m->op->stop(m, p);
  }
} //可见seq_read函数分别调用了自定义的seq_operation结构中的回调函数start,show,next,stop等函数。
这样就将vfs层的sys_read->seq_read(调用我们自己定义的seq_operation的start,show,next,stop等函数),从而可以根据我们自己选择的方式去显示我们的数据。

 关于proc,seq_file的使用和介绍参考:

在 Linux 下用户空间与内核空间数据交换的方式,第 2 部分: procfs、seq_file、debugfs和relayfs

 

http://www.ibm.com/developerworks/cn/linux/l-kerns-usrs2/index.html

posted on 2010-12-16 22:40 lstar 阅读(1531) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

统计

常用链接

留言簿

文章档案

搜索

最新评论