Seq_file文件系统实例剖析
http://blog.chinaunix.net/uid-24432676-id-2607766.html
另
http://www.cnblogs.com/qq78292959/archive/2012/06/13/2547335.html
Seq_file文件系统实例剖析的两篇文章 2011-05-07 21:51:29
分类: LINUX
文章一:
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 /* for use of init_net*/
#include /* We're doing kernel work */
#include /* Specifically, a module */
#include /* Necessary because we use proc fs */
#include /* 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文件。有兴趣的朋友可以测试一下。
总结待续
[ 本帖最后由 dreamice 于 2008-11-13 21:03 编辑 ]![]()
seq.jpg
(10.69 KB) 2008-11-13 18:04
执行流程图
|
内容简介: 本 UNIX 为了能给大家一个具体形象的认识,我们首先来看一段用序列文件接口通过proc文件导出内核双向循环链接表的实例代码: #include <linux/kernel.h> static struct mutex lock; static void add_one(void) mutex_lock(&lock); static ssize_t _seq_write(struct file *file, const char __user * buffer, static int _seq_show(struct seq_file *m, void *p) seq_printf(m, "value: %d\n", data->value); static void *_seq_start(struct seq_file *m, loff_t *pos) static void *_seq_next(struct seq_file *m, void *p, loff_t *pos) static void _seq_stop(struct seq_file *m, void *p) static struct seq_operations _seq_ops = { static int _seq_open(struct inode *inode, struct file *file) static struct file_operations _seq_fops = { static void clean_all(struct list_head *head) while (!list_empty(head)) { static int __init init(void) mutex_init(&lock); add_one(); entry = create_proc_entry("my_data",S_IWUSR | S_IRUGO, NULL); return 0; static void __exit fini(void) module_init(init);
struct seq_operations { start(): 2、重要的数据结构 seq_hello.c #define PROC_NAME "test_proc" typedef struct item user_item items[4]; MODULE_AUTHOR("ZHANG JIE:iptabler@mail.com"); static void *my_seq_start(struct seq_file *s, loff_t *pos) if ( *pos == 0 ) { /* yes => return a non null value to begin the sequence */ return &counter; } else { /* no => it's the end of the sequence, return end to stop reading */ *pos = 0; return NULL; }}static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos){ unsigned long *tmp_v = (unsigned long *)v; if (*pos < MAX_LINES) { (*tmp_v)++; (*pos)++; return tmp_v; } else { *pos = 0; return NULL; }}static void my_seq_stop(struct seq_file *s, void *v){ printk("Invoke stop\n");}static int my_seq_show(struct seq_file *s, void *v){ int i; loff_t *spos = (loff_t *) v; for (i = 0; i < 4; i++) { items[i].key = *spos; } items[0].value = '0'; items[1].value = '1'; items[2].value = '2'; items[3].value = '3'; seq_printf(s, "%ld=%c,%ld=%c,%ld=%c,%ld=%c;\n", items[0].key, items[0].value, items[1].key, items[1].value, items[2].key, items[2].value, items[3].key, items[3].value); 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 /proc/net/test_proc success!\n"); return 0;}void cleanup_module(void){ remove_proc_entry(PROC_NAME, init_net.proc_net); printk(KERN_INFO"Remove /proc/net/test_proc success!\n");}Makefileobj-m := seq_hello.oKDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default: $(MAKE) -C $(KDIR) M=$(PWD) modulesclean: $(RM) *.o *.mod.c *.ko *.symvers *.markers *.order[root@zj:~/Desktop/net/seq]# cat /proc/net/test_proc |
Seq_file文件系统实例剖析的更多相关文章
- Android实例剖析笔记(四)
摘要:分析NoteEditor这个类和以及Content Provider机制 NoteEditor深入分析 首先来弄清楚“日志编辑“的状态转换,通过上篇文章的方法来做下面这样一个实验,首先进入“日志 ...
- 基于栈的指令集与基于寄存器的指令集详细比对及JVM执行栈指令集实例剖析
基于栈的指令集与基于寄存器的指令集详细比对: 这次来学习一些新的概念:关于Java字节码的解释执行的一种方式,当然啦是一些纯理论的东东,但很重要,在之后会有详细的实验来对理论进行巩固滴,下面来了解一下 ...
- Android实例剖析笔记(一)
摘要:用实例讲解Andriod的开发过程 开卷语 俗话说,“熟读唐诗三百首,不会作诗也会吟”.最近收集了很多Android的示例代码,从这些代码的阅读和实验中学习到很多知识,从而产生写这个系列的打算, ...
- python直接赋值、深浅拷贝实例剖析
根据数据类型分为两部分进行剖析: int.str类型 list.tuple.dict类型等 1. int.str类型 [int类型实例] >>> import copy ...
- JavaScript实战实例剖析——(激励倒计时日历)
如今JavaScript在前端开发中的地位越来越高,掌握JavaScript的深度往往能决定你职业道路深远,这次通过制作 带着倒计时功能的激励日历的小实例,进一步细致的掌握JavaScript的语法与 ...
- Android实例剖析笔记(二)
摘要:用实例讲解Andriod的开发过程,以NotesList为实例介绍Android的菜单机制 简介 android提供了三种菜单类型,分别为options menu,context menu,su ...
- Android实例剖析笔记(三)
摘要:点介绍Activity的生命周期,通过一个简单的实验来摸索状态转换的机制 Activity的生命周期 Activity类中有许多onXXX形式的函数可以重载,比如onCreate,onStart ...
- Java构造方法与析构方法实例剖析
Java构造方法 类有一个特殊的成员方法叫作构造方法,它的作用是创建对象并初始化成员变量.在创建对象时,会自动调用类的构造方法. 构造方法定义规则:Java 中的构造方法必须与该类具有相同的名字,并且 ...
- flv格式详解+实例剖析
简介 FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧.封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式.另外由于当前浏览 ...
随机推荐
- # 关于Apache的25个初中级面试题
注:本文从自己的Markdown博客复制出,除标题字体加粗.代码风格改变.图片重新上传外其余均为markdown语法. 标签(空格分隔): LAMP --- 原文:[关于Apache的25个初中级面试 ...
- selenium启动firefox时加载扩展
有些时候,我们测试需要用到插件或者已经导入的证书(比如金融和安全加密行业),而selenium启动firefox时会打开一个新的,不含有任何插件和个人证书的firefox(等同于全新安装后第一次打开的 ...
- 1 UML基础
学习设计模式的过程中,发现相关的作者们都会用UML类图来表示一个模式的整体脉络,这种方式确实直观明了,既能体现宏观思路.又能兼顾实现细节.真的是很妙的工具.在开始正式学习设计模式之前,有必要对UML有 ...
- java对cookie的操作
java对cookie的操作比较简单,主要介绍下建立cookie和读取cookie,以及如何设定cookie的生命周期和cookie的路径问题. 建立一个无生命周期的cookie,即随着浏览器的关闭即 ...
- checkbox全选,反选,取消选择 jquery
checkbox全选,反选,取消选择 jquery. //checkbox全部选择 $(":checkbox[name='osfipin']").each(function(){ ...
- SAP 应用服务负载均衡的实现
共两步,一是服务器的设置,二是客户端登陆设置. 先在SAP中使用SMLG 进行服务器分组.实例名是SAP系统中定义过的,你没法删也没改.(可能是俺不会,会的教教).我们先建一个Gro ...
- “破解大牛是怎么炼成的”之壳与ESP定律
文章难易度:★★★ 文章阅读点/知识点:逆向破解 文章作者:Sp4ce 文章来源:i春秋 关键字:网络 信息安全技术 本文参与i春秋社区原创文章奖励计划,未经许可禁止转载! 一.前言 通过前面几篇 ...
- iOS 三方库fmdb 的使用
使用fmdb 做本地数据的存储非常方便, 1. github 上搜索fmdb 下载压缩包 导入到工程中 (如果你的mac 有cocoapod 也可以直接通过cocoapod 添加) 2. 以下代码是通 ...
- 操作系统开发系列—9.Loader
一个操作系统从开机到开始运行,大致经历“引导—>加载内核入内存—>跳入保护模式—>开始执行内核”这样一个过程.也就是说,在内核开始执行之前不但要加载内核,而且还有准备保护模式等一系列 ...
- iOS通用的MVC模式项目框架MobileProject
最近项目比较不赶的情况下,决定把一些通用.常用的内容集成在一个项目框架中,意在新项目中可以快速搭建:其实经过几个项目后,总是有一些重复的创建工作,可以使用本项目的内容直接进行开发:采用的是MVC的分层 ...