linux中proc文件系统 -- ldd3读书笔记
1./proc 文件系统概述
/proc 文件系统是由软件创建,被内核用来向外界报告信息的一个文件系统。/proc 下面的每一个文件都和一个内核函数相关联,当文件的被读取时,与之对应的内核函数用于产生文件的内容。我们已经见到了很多这样的文件,例如,/proc/modules 总是返回当前内核中加载的模块。
/proc 广泛的应用在 linux 文件系统中,现代 linux 发行版上的许多应用程序,例如 ps ,top 和 uptime 都从 /proc 获取他们所需要的信息。一些驱动程序也通过 /proc 文件系统报告信息,当然你的驱动程序也可以这么做。 /proc 文件系统是动态的,所以你的模块可以在任何时候添加或者删除入口。完全特征的 /proc 入口可能会是一个复杂的猛兽,它们既可以读也可以写。然而,大多数时候,/proc 中的文件是只读的。这里考虑的是只读的 /proc 文件。
然而,在继续之前,必须强调在 /proc 下面添加文件是不提倡的。/proc 文件系统被内核开发者看作是不可控制的混乱,这和它最初的目的--报告系统中运行的进程的信息相差十万八千里。在新的代码中推荐的获取信息的方式是通过 sysfs 。但是,使用 sysfs 是需要对 linux 设备模型有一个理解。并且,/proc 下面的文件较容易创建,并且完全符合调试的目的,所以才会学习 /proc 文件系统。
2.创建 /proc 文件
如果你定义了一个 read_proc 函数,你需要将它和 /proc 层次中的入口联系起来。这是通过一个叫做 create_proc_read_entry 的函数来实现的,这个函数的函数原型如下:
- struct proc_dir_entry *create_proc_read_entry(const char *name,mode_t mode,struct proc_dir_entry *base,read_proc_t *read_proc,void *data);
上面的函数原型中,name 就是要创建的文件的名字;mode 就是文件的保护掩码,可以使用 0 来使用系统默认的掩码;base 指定了创建的文件所在的目录,如果 base 为 NULL,创建的文件就存在于 /proc 目录之下;read_proc 就是实现这个文件的函数;data 参数被内核忽略,但是却被传递给 read_proc 函数。举一个例子:
- create_proc_read_entry("scullmem", 0/*default mode*/, NULL /*parent dir*/, scull_read_procmem, NULL /*client data*/);
这个例子中,我们在 /proc 下面创建了一个文件,名字为 scullmem,采用的是系统默认的保护权限。
目录入口指针可以用来在 /proc 下创建整个目录架构,然而,注意将一个文件放到 /proc 子目录中的一个更加容易的做法是将子目录的名字作为要创建的新文件名字的一部分路径,只要那个子目录已经存在。例如一个经常被忽略的惯例就是和驱动程序相关的 /proc 文件应该放到一个 driver 子目录中。例如,上面的例子中,我们想要将所创建的文件 scullmem 放到 driver 中,只需要将第一个参数修改为 "driver/scullmem" 就可以了。
/proc 中文件在模块被卸载的时候应该被删除。remove_proc_entry 所做的事情和 create_proc_read_entry 所做的事情相反。例如:
- remove_proc_entry("scullmem",NULL /*parent dir*/);
不能成功的移除文件将导致这个文件在不合适的时候被调用,或者是,模块被卸载后,内核就崩溃了。当向上面一样使用 /proc 的时候,必须记住几个麻烦的事——难怪现在不推荐使用这种方式了。最重要的问题就是在删除 /proc 文件的时候了,在删除的时候文件可能仍然在使用。因为 /proc 文件没有相关的所有者,所以使用它们的时候并不会对引用计数起作用。这个问题可以简单的通过在删除文件之前使用下面的命令引起:
- sleep 100 < /proc/myfile
另外一个问题是注册了两个一样名字的文件。内核信任驱动程序,并不检查文件的名字是否备注册过,所以如果你不小心,就可能会注册多个相同名字的文件。这就像在教室里发生的著名的问题一样,这些文件不能区分,不管是你在访问它们还是调用remove_proc_entry的时候。
3.在 /proc中实现文件
所有使用 /proc 的模块应该包括 <linux/proc_fs.h> 头文件来定义合适的函数。创建一个只读的 /proc 文件,你的驱动程序必须实现一个函数,当这个文件被读时,来产生一些数据。当一些进程使用 read 函数读取文件的时候,请求就通过这个函数到达了你的模块。我们会首先看一下这个函数,并且之后介绍注册的接口。当一个进程读取 /proc 文件的时候,内核就分配了一页的内存,驱动程序可以将要返回给用户空间的数据写到这个页里面。那个缓存被传递给了你的 read_proc 函数。read_proc 函数的原型如下:
- int (*read_proc)(char *page,char **start,off_t offset,int count,int *eof,void *data);
参数 page 是缓冲区的指针,你可以往里面写入数据;start 被函数用来说明感兴趣的数据被写到了页的位置。offset 和 count 与 read 函数的参数意义相同;eof 指向了一个整数,必须由驱动程序来设定报告没有返回的数据了,data 是依赖于特定的驱动的数据指针,你可以用来作为内部记账。
这个函数应该返回写入到页缓冲区中的数据字节数。就像 read 函数一样。其它的输出是 *eof 和 *start 。eof 是一个简单的标记,但是 start 的使用方法是有写复杂的,它的目的视为了帮助实现大的(超过一页)的 /proc 文件。start 参数并不常用,它的目的使用来指示返回给用户空间的住局在一页中的哪个位置。当 read_proc 函数被调用的时候,*start 参数将会被设置为 NULL。如果你保留它为 NULL 的话,内核会假设数据放到页里面时,参数 offset 为 0。换句话说,内核假设了一个头脑简单的 read_proc 版本,它把虚拟文件的所有内容写到页里面,而忽略了 offset 参数。相反,如果给 *start 设置了一个不是 NULL 的值,内核就假设由 *start 指向的数据将 offset 考虑在内,并且已经准备好返回给用户空间了。一般来说,简单的 proc_read 方法返回很少量的数据常常忽略了 *start 参数。更加复杂的方法才会设置页的 *start 的值,并且仅仅将数据放到所请求的 offset 那里。
4.实例
在这里,我们写了一个简单的例子来演示一下 /proc 的使用:
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/proc_fs.h>
- int read_proc(char *page,char **start,off_t offset,int count,int *eof,void *data);
- static int __init test_proc_init(void)
- {
- create_proc_read_entry("read_proc",0,NULL,read_proc,NULL);
- return 0;
- }
- static void __exit test_proc_exit(void)
- {
- remove_proc_entry("read_proc",NULL);
- }
- int read_proc(char *page,char **start,off_t offset,int count,int *eof,void *data)
- {
- int len = sprintf(page,"%s\n","hello world");
- return len;
- }
- module_init(test_proc_init);
- module_exit(test_proc_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("wangxq");
当插入这个模块到内核之后,使用命令:
- cat /proc/read_proc
就会看到输出 hello world。
转:http://blog.csdn.net/xiaocainiaoshangxiao/article/details/38091459
linux中proc文件系统 -- ldd3读书笔记的更多相关文章
- Linux内核设计与实现之虚拟文件系统的读书笔记
Linux内核设计与实现之虚拟文件系统的读书笔记 虚拟文件系统(VFS) 为用户空间提供了文件和文件系统相关的接口. 文件系统抽象层 内核在底层文件系统上建立了一个抽象层, 该抽象层使Linux能够支 ...
- Linux Shell脚本攻略 读书笔记
Linux Shell脚本攻略 读书笔记 这是一本小书,总共253页,但内容却很丰富,书中的示例小巧而实用,对我这样总是在shell门前徘徊的人来说真是如获至宝:最有价值的当属文本处理,对这块我单独整 ...
- Linux内核设计与实现 读书笔记 转
Linux内核设计与实现 读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...
- linux 中/proc 详解
proc 文件系统 在Linux中有额外的机制可以为内核和内核模块将信息发送给进程-- /proc 文件系统.最初设计的目的是允许更方便的对进程信息进行访问(因此得名),现在它被每一个有有趣的东西报告 ...
- Linux中/proc目录下文件详解
转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...
- Linux中/proc目录下文件详解(转贴)
转载:http://www.sudu.cn/info/index.php?op=article&id=302529 Linux中/proc目录下文件详解(一) 声明:可以自由转载本文, ...
- 全面了解Linux下Proc文件系统
全面了解Linux下Proc文件系统 Proc是一个虚拟文件系统,在Linux系统中它被挂载于/proc目录之上.Proc有多个功能 ,这其中包括用户可以通过它访问内核信息或用于排错,这其中一个非 ...
- linux 使用/proc文件系统 实现用户空间与内核模块之间通信
项目中可能会用到用户态和内核模块之间进行通信的功能.想到linux系统本身很多通信都是通过/proc文件系统来的,比如修改网络中连接跟踪表连接数限制/proc/sys/net/netfilter/nf ...
- Linux内核设计与实现 读书笔记
第三章 进程管理 1. fork系统调用从内核返回两次: 一次返回到子进程,一次返回到父进程 2. task_struct结构是用slab分配器分配的,2.6以前的是放在内核栈的栈底的:所有进程的ta ...
随机推荐
- ThinkPHP中initialize和construct调用父类的区别
http://blog.topok.net/archives/142 需要加parent::_initialize();
- extern "C"——用“C”来规约在C++中用C的方式进行编译和链接
C++中的extern “C”用法详解 extern "C"表明了一种编译规约,其中extern是关键字属性,“C”表征了编译器链接规范.对于extern "C& ...
- oc对象的内存管理
oc没有java的垃圾回收机制,所以对象的内存释放很重要,基本数据类型,我们不用理会,编译器会处理: oc的每个对象内部都由一个计数器,用来记录当前有几个指针在指向该对象:当计数器为0时该对象会从内存 ...
- aspnet_regiis.exe 的用法
使用aspnet_regiis.exe注册.NET Framework 重新安装IIS以后,需要用aspnet_regiis.exe来注册.NET Framework, 如下: C:\WINDOWS\ ...
- Python Socket File Transfer
I have a RPi which I intented to use it to crawl data. The development environment in RPi is very ba ...
- lamada 表达式之神奇的groupby
少说话多干活 先定义一个测试用的实体,接下来会用字段Name进行分组的 public class TestToRun { public string Name { get; set; }//名称 pu ...
- 剑指offer--面试题7
//两个栈实现一个队列 #include<stack> //STL #include<iostream> using namespace std; template<cl ...
- [bzoj 3031] 理科男
题意 给定一个进制分数 求是否是循环小数,且求出循环节长度 题解 暴力 il int find(int p){ int head=last[p%mod]; while(head&&pr ...
- transparent 的新问题
http://msdn.microsoft.com/en-us/library/windows/desktop/bb172255(v=vs.85).aspx 人物透明 显示是纹理和白色混合 开始怀疑是 ...
- 01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即加载实现--NHibernateUtil.Initialize()和添加fetch关键字的HQL查询
相关资料: http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html 问题的提出: 1.延迟加载,可能会引起session已经关闭的异常,例 ...