简单的proc动态文件系统模块
2017-02-23 18:09
337 查看
又开学了呢..寒假在家沉迷血源,并没怎么看书.新学期继续努力吧.
最近在看文件系统相关的东西,于是想起之前写的读取/proc下的文件监控系统数据的程序,proc也是一种文件系统,不过他只存在于内存中,所以叫做伪文件系统.也是早期用户能简单和内核进行交互的方式之一,现在也许用在调试内核程序比较多(?).
还是以模块的形式加载我们制作的动态文件系统.先是注册模块,
注册my_proc_init为模块的入口,在加载的时候就会调用my_proc_init函数,同理卸载的时候调用my_proc_exit.
之后调用proc_create这个接口为我们在/proc下创建一个名为hello_proc的文件.
此外看了下网上还有使用create_proc_entry的方法,但是我这边无法编译说找不到这个函数定义,差了下这个方法在3.10以上的版本的内核中已经被弃用了.so..//
先来看看这个函数的定义
第一个name是你的proc文件的名字,第二个是你创建的文件的权限,我们填0表示的权限是是0444,安装之后是这样的:
第三个参数是你创建的文件位置(可以这么说吧),你可以通过proc_mkdir现在/proc下创建一个文件夹项目,在把这个文件夹传入给parent,这样proc文件就生成在了你创建的目录项下了.NULL就表示直接创建.
最后一个file_operations就是该文件的操作函数了.我们通过一个结构体来定义.
想看完整结构在linux/include/linux/fs.h中.
下面三个基本不会变,主要是有一个.open和.write,分别记录文件被读取和写入时的动作.
先用seq_file对象打开文件,再使用seq_file中定义的标准输出的方法输出字符.
至于这个seq_file是个司马东西,大致就是虽然以前就有proc系统的存在,但是在数据大小使用方面很有局限性,于是某人就想了这个方法,用迭代器的形式迭代遍历元素,比如你有一个结构体的数组,就可以用pos来记录迭代的位置.
一个很典型的例子就是/proc/device,如果你cat这个文件就会打印出所有的设备名.看下源代码
devinfo_ops中记录着迭代的操作,顺序时start->show->next->show….一直到结束调用stop.在next中每次把*pos++记录循环的次数,然后返回给static int devinfo_show(struct seq_file *f, void *v)中的v.
当然如果数据够小也可以直接用for进行循环,这样就和我们平时写的没什么区别了.
之后写个Makefile编译成模块.
如果说找不到目录的话请检查下/usr/src/kernels/$(shell uname -r)/build指向的地址再把上面替换调(神tm内核版本和kernel-headers版本是不一样的.)
有兴趣可以读下https://github.com/jesstess/ldd4/blob/master/scull/main.c,写的方法比较全.
结束结束.
最近在看文件系统相关的东西,于是想起之前写的读取/proc下的文件监控系统数据的程序,proc也是一种文件系统,不过他只存在于内存中,所以叫做伪文件系统.也是早期用户能简单和内核进行交互的方式之一,现在也许用在调试内核程序比较多(?).
还是以模块的形式加载我们制作的动态文件系统.先是注册模块,
#include <linux/module.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/kernel.h> #include <asm/uaccess.h> #define PROC_NAME "hello_proc" static int __init my_proc_init(void) { printk(KERN_INFO "init and create proc"); proc_create(PROC_NAME, 0, NULL, &hello_proc_fops); } static void __exit my_proc_exit(void) { remove_proc_entry(PROC_NAME, NULL); } MODULE_LICENSE("GPL"); module_init(my_proc_init); module_exit(my_proc_exit);
注册my_proc_init为模块的入口,在加载的时候就会调用my_proc_init函数,同理卸载的时候调用my_proc_exit.
之后调用proc_create这个接口为我们在/proc下创建一个名为hello_proc的文件.
此外看了下网上还有使用create_proc_entry的方法,但是我这边无法编译说找不到这个函数定义,差了下这个方法在3.10以上的版本的内核中已经被弃用了.so..//
先来看看这个函数的定义
static inline struct proc_dir_entry *proc_create( const char *name, mode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops)
第一个name是你的proc文件的名字,第二个是你创建的文件的权限,我们填0表示的权限是是0444,安装之后是这样的:
[root@localhost proc]# ls /proc/hello_proc -la -r--r--r--. 1 root root 0 Feb 23 17:25 /proc/hello_proc
第三个参数是你创建的文件位置(可以这么说吧),你可以通过proc_mkdir现在/proc下创建一个文件夹项目,在把这个文件夹传入给parent,这样proc文件就生成在了你创建的目录项下了.NULL就表示直接创建.
最后一个file_operations就是该文件的操作函数了.我们通过一个结构体来定义.
static const struct file_operations hello_proc_fops = { .owner = THIS_MODULE, .open = hello_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, };
想看完整结构在linux/include/linux/fs.h中.
下面三个基本不会变,主要是有一个.open和.write,分别记录文件被读取和写入时的动作.
static int hello_proc_show(struct seq_file *m, void *v) { seq_printf(m, "Hello proc!\n"); return 0; } static int hello_proc_open(struct inode *inode, struct file *file) { return single_open(file, hello_proc_show, NULL); }
先用seq_file对象打开文件,再使用seq_file中定义的标准输出的方法输出字符.
至于这个seq_file是个司马东西,大致就是虽然以前就有proc系统的存在,但是在数据大小使用方面很有局限性,于是某人就想了这个方法,用迭代器的形式迭代遍历元素,比如你有一个结构体的数组,就可以用pos来记录迭代的位置.
一个很典型的例子就是/proc/device,如果你cat这个文件就会打印出所有的设备名.看下源代码
#include <linux/fs.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> static int devinfo_show(struct seq_file *f, void *v) { int i = *(loff_t *) v; if (i < CHRDEV_MAJOR_HASH_SIZE) { if (i == 0) seq_puts(f, "Character devices:\n"); chrdev_show(f, i); } #ifdef CONFIG_BLOCK else { i -= CHRDEV_MAJOR_HASH_SIZE; if (i == 0) seq_puts(f, "\nBlock devices:\n"); blkdev_show(f, i); } #endif return 0; } static void *devinfo_start(struct seq_file *f, loff_t *pos) { if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE)) return pos; return NULL; } static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) { (*pos)++; if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE)) return NULL; return pos; } static void devinfo_stop(struct seq_file *f, void *v) { /* Nothing to do */ } static const struct seq_operations devinfo_ops = { .start = devinfo_start, .next = devinfo_next, .stop = devinfo_stop, .show = devinfo_show }; static int devinfo_open(struct inode *inode, struct file *filp) { return seq_open(filp, &devinfo_ops); } static const struct file_operations proc_devinfo_operations = { .open = devinfo_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; static int __init proc_devices_init(void) { proc_create("devices", 0, NULL, &proc_devinfo_operations); return 0; } module_init(proc_devices_init);
devinfo_ops中记录着迭代的操作,顺序时start->show->next->show….一直到结束调用stop.在next中每次把*pos++记录循环的次数,然后返回给static int devinfo_show(struct seq_file *f, void *v)中的v.
当然如果数据够小也可以直接用for进行循环,这样就和我们平时写的没什么区别了.
之后写个Makefile编译成模块.
SOURCE = procfs.c obj-m += procfs.o proc-objs := $(SOURCE:.c=.o) all: make -C /usr/src/kernels/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
如果说找不到目录的话请检查下/usr/src/kernels/$(shell uname -r)/build指向的地址再把上面替换调(神tm内核版本和kernel-headers版本是不一样的.)
[root@localhost proc]# insmod procfs.ko [root@localhost proc]# cat /proc/ [root@localhost proc]# cat /proc/hello_proc Hello proc!
有兴趣可以读下https://github.com/jesstess/ldd4/blob/master/scull/main.c,写的方法比较全.
结束结束.
相关文章推荐
- 一个简单的可移植 模块/系统动态内存 跟踪方法
- linux 使用/proc文件系统 实现用户空间与内核模块之间通信
- proc文件系统模块编程-常见错误及解决方法
- [译]5.10. Tuning via /procs Filesystem 通过/proc文件系统来调整内核模块
- 简单案例教你用PROC文件系统获取进程信息 推荐
- 简单案例教你用PROC文件系统获取进程信息
- /proc/kcore失效,调试其文件系统相关模块,使重新正常工作
- Solaris下利用/proc文件系统特性简单构建log系统
- 文件系统的简单操作
- 本人做的 透明动态加密解密文件系统 使用说明--------招代理商
- 理解 Proc 文件系统(ZT)
- proc文件系统面面谈(转贴)
- Linux基础-文件系统简单命令
- proc文件系统-z(非常棒的对proc的描述)
- Linux系统面面观 PROC文件系统详细介绍
- proc文件系统5大功能
- 简单文件系统的实现
- 简单文件系统的实现
- autofs服务动态自动挂载各种文件系统
- 理解 Proc 文件系统(转)