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的使用和介绍参考:
联系客服