您的位置 首页 应用

用户与内核空间数据交换的方法之一seq_file

用户与内核空间数据交换的方式之一seq_file-要想使用seq_file功能,开发者需要包含头文件linux/seq_file.h,并定义与设置一个seq_operations结构(类似于file_operations结构)

一般地,内核经过在procfs文件体系下树立文件来向用户空间供给输出信息,用户空间能够经过任何文本阅览运用检查该文件信息,可是procfs 有一个缺点,假如输出内容大于1个内存页,需求屡次读,因而处理起来很难,别的,假如输出太大,速度比较慢,有时会呈现一些意想不到的状况, Alexander Viro完成了一套新的功用,使得内核输出大文件信息更简略,该功用呈现在2.4.15(包括2.4.15)今后的一切2.4内核以及2.6内核中,特别 是在2.6内核中,现已大量地运用了该功用。

要想运用seq_file功用,开发者需求包括头文件linux/seq_file.h,并界说与设置一个seq_operations结构(类似于file_operaTIons结构): 

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_file文件的读开端方位,回来实践读开端方位,假如指定的方位超越文件结尾,应当回来NULL,start函数能够有一个特别的回来SEQ_START_TOKEN,它用于让show函数输出文件头,但这只能在pos为0时运用,next函数用于把seq_file文件的当时读方位移动到下一个读方位,回来实践的下一个读方位,假如现已抵达文件结尾,回来NULL,stop函数用于在读完seq_file文件后调用,它类似于文件操作close,用于做一些必要的整理,如开释内存等,show函数用于格局化输出,假如成功回来0,不然回来出错码。
Seq_file也界说了一些辅佐函数用于格局化输出:

/*函数seq_putc用于把一个字符输出到seq_file文件*/
int seq_putc(struct seq_file *m, char c);

/*函数seq_puts则用于把一个字符串输出到seq_file文件*/
int seq_puts(struct seq_file *m, const char *s);

/*函数seq_escape类似于seq_puts,仅仅,它将把第一个字符串参数中呈现的包括在第二个字符串参数

中的字符依照八进制方式输出,也即对这些字符进行转义处理*/
int seq_escape(struct seq_file *, const char *, const char *);

/*函数seq_printf是最常用的输出函数,它用于把给定参数依照给定的格局输出到seq_file文件*/
int seq_printf(struct seq_file *, const char *, …)__attribute__ ((format(printf,2,3)));

/*函数seq_path则用于输出文件名,字符串参数供给需求转义的文件名字符,它首要供文件体系运用*/
int seq_path(struct seq_file *, struct vfsmount *, struct dentry *, char *);

在界说了结构struct seq_operaTIons之后,用户还需求把翻开seq_file文件的open函数,以便该结构与对应于seq_file文件的struct file结构相关起来,例如,struct seq_operaTIons界说为:

struct seq_operations exam_seq_ops = {
.start = exam_seq_start,
.stop = exam_seq_stop,
.next = exam_seq_next,
.show = exam_seq_show
};

那么,open函数应该如下界说:
 

static int exam_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &exam_seq_ops);
};

留意,函数seq_open是seq_file供给的函数,它用于把struct seq_operations结构与seq_file文件相关起来。
最终,用户需求如下设置struct file_operations结构: 

struct file_operations exam_seq_file_ops = {
.owner = THIS_MODULE,
.open = exm_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};


留意,用户仅需求设置open函数,其它的都是seq_file供给的函数。
然后,用户创立一个/proc文件并把它的文件操作设置为exam_seq_file_ops即可:

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


关于简略的输出,seq_file用户并不需求界说和设置这么多函数与结构,它仅需界说一个show函数,然后运用single_open来界说open函数就能够,以下是运用这种简略方式的一般过程:
1.界说一个show函数

int exam_show(struct seq_file *p, void *v)
{

}


2. 界说open函数

int exam_single_open(struct inode *inode, struct file *file)
{
return(single_open(file, exam_show, NULL));
}

留意要运用single_open而不是seq_open。
3. 界说struct file_operations结构  

struct file_operations exam_single_seq_file_operations = {
.open = exam_single_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};


留意,假如open函数运用了single_open,release函数有必要为single_release,而不是seq_release。 下面给出了一个运用seq_file的详细比如seqfile_exam.c,它运用seq_file供给了一个检查当时体系运转的一切进程的/proc接口,在编译并刺进该模块后,用户经过指令”cat /proc/exam_esq_file”能够检查体系的一切进程。

//kernel module: seqfile_exam.c
#include #include #include #include #include #include

static struct proc_dir_entry *entry;

static void *l_start(struct seq_file *m, loff_t * pos)
{
loff_t index = *pos;

if (index == 0) {
seq_printf(m, “Current all the processes in system:\n”
“%-24s%-5s\n”, “name”, “pid”);
return &init_task;
}
else {
return NULL;
}
}

static void *l_next(struct seq_file *m, void *p, loff_t * pos)
{
task_t * task = (task_t *)p;

task = next_task(task);
if ((*pos != 0) && (task == &init_task)) {
return NULL;
}
++*pos;
return task;
}

static void l_stop(struct seq_file *m, void *p)
{
}

static int l_show(struct seq_file *m, void *p)
{
task_t * task = (task_t *)p;

seq_printf(m, “%-24s%-5d\n”, task->comm, task->pid);
return 0;
}

static struct seq_operations exam_seq_op = {
.start = l_start,
.next = l_next,
.stop = l_stop,
.show = l_show
};

static int exam_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &exam_seq_op);
}

static struct file_operations exam_seq_fops = {
.open = exam_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};

static int __init exam_seq_init(void)
{

entry = create_proc_entry(“exam_esq_file”, 0, NULL);
if (entry)
entry->proc_fops = &exam_seq_fops;

return 0;
}

static void __exit exam_seq_exit(void)
{
remove_proc_entry(“exam_esq_file”, NULL);
}

module_init(exam_seq_init);
module_exit(exam_seq_exit);
MODULE_LICENSE(“GPL”);

 

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/90046.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部