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 的函数来实现的,这个函数的函数原型如下:

  1. 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 函数。举一个例子:

  1. 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 所做的事情相反。例如:

  1. remove_proc_entry("scullmem",NULL /*parent dir*/);

不能成功的移除文件将导致这个文件在不合适的时候被调用,或者是,模块被卸载后,内核就崩溃了。当向上面一样使用 /proc 的时候,必须记住几个麻烦的事——难怪现在不推荐使用这种方式了。最重要的问题就是在删除 /proc 文件的时候了,在删除的时候文件可能仍然在使用。因为 /proc 文件没有相关的所有者,所以使用它们的时候并不会对引用计数起作用。这个问题可以简单的通过在删除文件之前使用下面的命令引起:

  1. sleep 100  < /proc/myfile

另外一个问题是注册了两个一样名字的文件。内核信任驱动程序,并不检查文件的名字是否备注册过,所以如果你不小心,就可能会注册多个相同名字的文件。这就像在教室里发生的著名的问题一样,这些文件不能区分,不管是你在访问它们还是调用remove_proc_entry的时候。

3.在 /proc中实现文件

所有使用 /proc 的模块应该包括 <linux/proc_fs.h> 头文件来定义合适的函数。创建一个只读的 /proc 文件,你的驱动程序必须实现一个函数,当这个文件被读时,来产生一些数据。当一些进程使用 read 函数读取文件的时候,请求就通过这个函数到达了你的模块。我们会首先看一下这个函数,并且之后介绍注册的接口。当一个进程读取 /proc 文件的时候,内核就分配了一页的内存,驱动程序可以将要返回给用户空间的数据写到这个页里面。那个缓存被传递给了你的 read_proc 函数。read_proc 函数的原型如下:

  1. 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 的使用:

  1. #include <linux/kernel.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/proc_fs.h>
  5. int read_proc(char *page,char **start,off_t offset,int count,int *eof,void *data);
  6. static int __init test_proc_init(void)
  7. {
  8. create_proc_read_entry("read_proc",0,NULL,read_proc,NULL);
  9. return 0;
  10. }
  11. static void __exit test_proc_exit(void)
  12. {
  13. remove_proc_entry("read_proc",NULL);
  14. }
  15. int read_proc(char *page,char **start,off_t offset,int count,int *eof,void *data)
  16. {
  17. int len = sprintf(page,"%s\n","hello world");
  18. return len;
  19. }
  20. module_init(test_proc_init);
  21. module_exit(test_proc_exit);
  22. MODULE_LICENSE("GPL");
  23. MODULE_AUTHOR("wangxq");

当插入这个模块到内核之后,使用命令:

  1. cat /proc/read_proc

就会看到输出 hello world。

转:http://blog.csdn.net/xiaocainiaoshangxiao/article/details/38091459

linux中proc文件系统 -- ldd3读书笔记的更多相关文章

  1. Linux内核设计与实现之虚拟文件系统的读书笔记

    Linux内核设计与实现之虚拟文件系统的读书笔记 虚拟文件系统(VFS) 为用户空间提供了文件和文件系统相关的接口. 文件系统抽象层 内核在底层文件系统上建立了一个抽象层, 该抽象层使Linux能够支 ...

  2. Linux Shell脚本攻略 读书笔记

    Linux Shell脚本攻略 读书笔记 这是一本小书,总共253页,但内容却很丰富,书中的示例小巧而实用,对我这样总是在shell门前徘徊的人来说真是如获至宝:最有价值的当属文本处理,对这块我单独整 ...

  3. Linux内核设计与实现 读书笔记 转

    Linux内核设计与实现  读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...

  4. linux 中/proc 详解

    proc 文件系统 在Linux中有额外的机制可以为内核和内核模块将信息发送给进程-- /proc 文件系统.最初设计的目的是允许更方便的对进程信息进行访问(因此得名),现在它被每一个有有趣的东西报告 ...

  5. Linux中/proc目录下文件详解

    转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...

  6. Linux中/proc目录下文件详解(转贴)

      转载:http://www.sudu.cn/info/index.php?op=article&id=302529   Linux中/proc目录下文件详解(一) 声明:可以自由转载本文, ...

  7. 全面了解Linux下Proc文件系统

    全面了解Linux下Proc文件系统   Proc是一个虚拟文件系统,在Linux系统中它被挂载于/proc目录之上.Proc有多个功能 ,这其中包括用户可以通过它访问内核信息或用于排错,这其中一个非 ...

  8. linux 使用/proc文件系统 实现用户空间与内核模块之间通信

    项目中可能会用到用户态和内核模块之间进行通信的功能.想到linux系统本身很多通信都是通过/proc文件系统来的,比如修改网络中连接跟踪表连接数限制/proc/sys/net/netfilter/nf ...

  9. Linux内核设计与实现 读书笔记

    第三章 进程管理 1. fork系统调用从内核返回两次: 一次返回到子进程,一次返回到父进程 2. task_struct结构是用slab分配器分配的,2.6以前的是放在内核栈的栈底的:所有进程的ta ...

随机推荐

  1. Ubuntu下Code::Blocks无法编译 /bin/sh: 1: g++ not found 解决办法

    Linux下Code::Blocks无法编译运行提示 /bin/sh: 1: g++ not found 的解决办法 今天在Ubuntu 12.04 软件中心中选装了Code::Blocks,安装完成 ...

  2. Halcon学习笔记之缺陷检测(二)

    例程:detect_indent_fft.hdev 说明:这个程序展示了如何利用快速傅里叶变换(FFT)对塑料制品的表面进行目标(缺陷)的检测,大致分为三步: 首先,我们用高斯滤波器构造一个合适的滤波 ...

  3. Careercup - Google面试题 - 4716965625069568

    2014-05-06 00:17 题目链接 原题: Given a -D matrix represents the room, obstacle and guard like the followi ...

  4. Careercup - Google面试题 - 5732809947742208

    2014-05-03 22:10 题目链接 原题: Given a dictionary, and a list of letters ( or consider as a string), find ...

  5. Caffe安装教程(原创)

    转载请注明地址 说明:本文档参考自Caffe官网的安装说明,http://caffe.berkeleyvision.org/installation.html 如果对安装过程中,需要用到的依赖不明,请 ...

  6. C# abstract function VS virtual function?

    An abstract function has to be overridden while a virtual function may be overridden. Virtual functi ...

  7. Codeforces Bubble Cup 8 - Finals [Online Mirror] B. Bribes lca

    题目链接: http://codeforces.com/contest/575/problem/B 题解: 把链u,v拆成u,lca(u,v)和v,lca(u,v)(v,lca(u,v)是倒过来的). ...

  8. apache nginx php不显示版本号

    apache 不显示版本号 http.conf 中的 修改为 ServerTokens ProdServerSignature Off 有的版本没有,在最后添加即可 php php.ini 中的 修改 ...

  9. PHP之cookie相关实例教程与经典代码

    ·php 中cookie和session的用法比较 ·php会话控制cookie与Session会话处理 ·php中利用cookie实现购物车实例 ·php中cookie与session应用学习笔记 ...

  10. 微信ios版6.2更新 聊天记录迁移更快捷朋友圈可翻译

    微信iPhone版昨日发布更新,版本号为微信 6.2 for iOS,主要特性有聊天记录迁移.发送图片更快捷.支持朋友圈翻译.手机充值可充流量查余额.可以通过展示二维码来收钱,和ytkah一起来瞧瞧吧 ...