网址:http://www.tinylab.org/show-the-usage-of-procfs-sysfs-debugfs/

1 前言

内核中有三个常用的伪文件系统:procfs,debugfs和sysfs。

  • procfs — The proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures.
  • sysfs — The filesystem for exporting kernel objects.
  • debugfs — Debugfs exists as a simple way for kernel developers to make information available to user space.

它们都用于Linux内核和用户空间的数据交换,但是适用的场景有所差异:

  • procfs 历史最早,最初就是用来跟内核交互的唯一方式,用来获取处理器、内存、设备驱动、进程等各种信息。
  • sysfs 跟 kobject 框架紧密联系,而 kobject 是为设备驱动模型而存在的,所以 sysfs 是为设备驱动服务的。
  • debugfs 从名字来看就是为debug而生,所以更加灵活。

它们仨的挂载方式类似,做个实验:

  1. $ sudo mkdir /tmp/{proc,sys,debug}
  2. $ sudo mount -t proc nondev /tmp/proc/
  3. $ sudo mount -t sys nondev /tmp/sys/
  4. $ sudo mount -t debugfs nondev /tmp/debug/

不过,默认情况下,它们分别挂载在/proc,/sys/,/sys/kernel/debug/。

下面简单介绍这三个文件系统的用法。在介绍之前,请记下他们的官方文档:

  • procfs — Documentation/filesystems/proc.txt
  • sysfs — Documentation/filesystems/sysfs.txt
  • debugfs — Documentation/filesystems/debugfs.txt

2 debugfs

  • API说明

    1. struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
    2. struct dentry *debugfs_create_file(const char *name, umode_t mode,
    3. struct dentry *parent, void *data,
    4. const struct file_operations *fops)
  • 参考实例

    drivers/base/power/wakeup.c:

    1. /**
    2. * wakeup_sources_stats_show - Print wakeup sources statistics information.
    3. * @m: seq_file to print the statistics into.
    4. */
    5. static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
    6. {
    7. struct wakeup_source *ws;
    8. seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
    9. "expire_count\tactive_since\ttotal_time\tmax_time\t"
    10. "last_change\tprevent_suspend_time\n");
    11. rcu_read_lock();
    12. list_for_each_entry_rcu(ws, &wakeup_sources, entry)
    13. print_wakeup_source_stats(m, ws);
    14. rcu_read_unlock();
    15. return 0;
    16. }
    17. static int wakeup_sources_stats_open(struct inode *inode, struct file *file)
    18. {
    19. return single_open(file, wakeup_sources_stats_show, NULL);
    20. }
    21. static const struct file_operations wakeup_sources_stats_fops = {
    22. .owner = THIS_MODULE,
    23. .open = wakeup_sources_stats_open,
    24. .read = seq_read,
    25. .llseek = seq_lseek,
    26. .release = single_release,
    27. };
    28. static int __init wakeup_sources_debugfs_init(void)
    29. {
    30. wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources",
    31. S_IRUGO, NULL, NULL, &wakeup_sources_stats_fops);
    32. return 0;
    33. }
  • 创建完的接口

    1. /sys/kernel/debug/wakup_sources
  • 给接口添加多级目录

    上述接口直接创建在 debugfs 根目录(/sys/kernel/debug)下,所以 debugfs_create_file的parent参数被设置成了NULL,如果要加一级目录,则可以先用 debugfs_create_dir 创建一级目录,例如,要创建:/sys/kernel/debug/power/wakeup_sources 的话,则需要:

    1. struct dentry *power;
    2. int err = -ENOMEM;
    3. power = debugfs_create_dir("power", NULL);
    4. if (!power)
    5. return err;
    6. wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources",
    7. S_IRUGO, power, NULL, &wakeup_sources_stats_fops);

3 procfs

  • API说明

    1. static inline struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
    2. static inline struct proc_dir_entry *proc_create(const char *name, umode_t mode,
    3. struct proc_dir_entry *parent, const struct file_operations *proc_fops)
  • 参考实例

    在上面例子的基础上,可以添加如下语句:

    1. static int __init wakeup_sources_debugfs_init(void)
    2. {
    3. proc_create("wakelocks", S_IFREG | S_IRUGO, NULL, &wakeup_sources_stats_fops);
    4. return 0;
    5. }
  • 创建后的接口

    1. /proc/wakelocks
  • 给接口添加多级目录

    这样创建的接口用起来跟 /sys/kernel/debug/wakeup_sources 没有任何差异,类似地,如果要加一级目录,例如 /proc/power/wakelocks,则可以:

    1. struct proc_dir_entry *power;
    2. int err = -ENOMEM;
    3. power = proc_mkdir("power", NULL);
    4. if (!power)
    5. return err;
    6. proc_create("wakelocks", S_IFREG | S_IRUGO, power, &wakeup_sources_stats_fops);

    proc_mkdir 用法跟 debugfs_create_dir 几无差异。

4 sysfs

  • API说明

    1. struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
    2. int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
    3. static inline int sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name)
    4. int device_create_file(struct device *dev, const struct device_attribute *attr)
  • 参考实例

    在 /sys/power 下创建一个 wakelocks 节点,用于读/写一个字符串。

    1. static char test_str[11];
    2. static ssize_t show_wakelocks(struct kobject *kobj, struct attribute *attr, char *buf)
    3. {
    4. int ret;
    5. ret = snprintf(buf, 10, "%s\n", test_str);
    6. return ret;
    7. }
    8. static ssize_t store_wakelocks(struct kobject *kobj, struct attribute *attr,
    9. const char *buf, size_t count)
    10. {
    11. int tmp;
    12. ret = sscanf(buf, "%10s", test_str);
    13. if (ret != 1)
    14. return -EINVAL;
    15. return count;
    16. }
    17. define_one_global_rw(wakelocks);
    18. static int __init wakelocks_init(void)
    19. {
    20. int ret;
    21. ret = sysfs_create_file(power_kobj, &wakelocks.attr);
    22. }
  • 创建后的节点

    1. /sys/power/test_node
  • 给接口添加多级目录

    咱们上面其实已经把 test_node 创建在 /sys/power 目录下,而非根目录 /sys 下,而参数 power_kobj 为内核已经在 kernel/power/main.c 创建的kobject对象。

    1. struct kobject *power_kobj;
    2. power_kobj = kobject_create_and_add("power", NULL);
    3. if (!power_kobj)
    4. return -ENOMEM;

    在 sysfs 中,有另外一个常见用法,那就是在一个 kobject 对应的目录下创建一个符号(属性文件)指向另外一个 kobject 对应的目录,通常这个是为了方便记忆和访问。这个API是 sysfs_create_link

    这种创建符号链接方法其实有一个很特殊的实例,那就是在驱动模型里头,有一个 class 的概念,它把挂在不同总线上,但是实现类似功能的设备进行归类,比如说 input 类,backlight 类等。

    如果设备属于一个现存的类,比如 backlight,那么可以用 backlight_device_register 创建,如果是I2C 设备,会先在I2C下创建 sysfs 访问节点,并创建一个符号链接到 backlight 类所属的目录下。

    当然,如果没有找到设备能挂的直观的类,也可以用 class_create 创建类,设备类通常会有一组默认的设备操作接口,例如 backlight 类有 bl_device_attributes,如果要创建更多的设备特定的节点,可以用device_create_file 或者 device_add_groups 创建节点或者节点群。

5 小结

通过比较发现,上述三个文件系统的 API 用法类似,而其中 debugfs 和 procfs 几乎有相同的参数,用的主要结构体是 struct file_operations,蛮多操作可以用 seq_* 家族的函数来实现。而 sysfs 则用到比较简单一些的 struct global_attr 结构体。对于提供给用户空间的节点,都可以轻松实现读写操作。

在创建目录方面,debugfs 和 procfs 类似,且比较简单。而 sysfs 要创建一级目录,需要先创建一个 kobject 对象。

为了简化设备模型依据总线创建的访问节点路径,sysfs 提供了API用于创建更简易的符号链接,可以创建到自己指定的目录下,也可以用设备类(Class)提供的API创建到设备类所属的目录下。

对于 sysfs,由于 kobject 与 device 的一对一依存关系,也可以直接用 device_create_file 来创建节点。

(转)Linux 文件系统:procfs, sysfs, debugfs 用法简介的更多相关文章

  1. Linux驱动开发3——devfs udev procfs sysfs debugfs傻傻地分不清楚

    Linux调试文件系统 1.1.procfs 早期的Linux内核中,内核通过procfs输出调试信息,可以在用户态通过读写procfs节点与内核进行交互,用来获取处理器.内存.设备驱动.进程等各种信 ...

  2. [转帖]linux lsof 用法简介

    linux lsof 用法简介 https://www.cnblogs.com/saneri/p/5333333.html 1.简介: lsof(list open files)是一个列出当前系统打开 ...

  3. linux 文件系统简介

    linux文件系统简介   文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文件系统,主要包括了linux磁盘分区和目录.挂载基 ...

  4. linux文件系统简介

    文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文件系统,主要包括了linux磁盘分区和目录.挂载基本原理.文件存储结构.软链接 ...

  5. Linux文件系统简介及常用命令

    在linux系统中一切皆是文件,下面简要总结了一下linux文件系统中分区类型.文件系统类型以及常用命令. 一.分区类型1.主分区:最多只能有四个2.扩展分区:只能有一个,也可以看做是主分区的一种.即 ...

  6. Linux文件系统简介----转载

    原文地址:Linux文件系统 文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文件系统,主要包括了linux磁盘分区和目录.挂载 ...

  7. 新一代 Linux 文件系统 btrfs 简介

    https://www.ibm.com/developerworks/cn/linux/l-cn-btrfs/ Btrfs 简介 文件系统似乎是内核中比较稳定的部分,多年来,人们一直使用 ext2/3 ...

  8. 【转载】linux文件系统简介

    文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文件系统,主要包括了linux磁盘分区和目录.挂载基本原理.文件存储结构.软链接 ...

  9. 存储那些事儿(二): 下一代Linux文件系统BTRFS简介

    BTRFS,通常念成 Butter FS,Better FS 或B-tree FS.下一代的Linux文件系统. 它基于写时拷贝(copy-on-write),支持高效的snapshot和clone. ...

随机推荐

  1. hdu 4455 动态规划

    思路:用sum[i]表示区间长度为i的不相同数的个数和,假使所有的数都不相同,那么sum[i]=sum[i-1]+n-i+1-later[i-1]; later[i-1]表示的是序列最后面的长度为i- ...

  2. Linux(CentOS6.5)系统安装Nginx

    Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.由俄罗斯的程序设计师Igor Sysoev所开发,供俄国大型的入口 ...

  3. 一些xcode5.1创建的工程在xcode6.0下不能编译的问题

    这是因为Xcode5.1.1自动选上了arm64架构, 建议解决办法是: Build Settings-ValidArchitectures中却掉arm64

  4. MySQL DBA 刚入职时如何快速拥抱新的环境

    方法何其多.这里介绍的是懒人做法.也就是.借助工具   但是.生产环境是不能随便安装程序的.肿么办?   没关系.我们伟大的percona 已经为我们考虑周详鸟      这里.我们要借助三个工具:  ...

  5. boost库区间range基本原理及使用实例

    由 www.169it.com 搜集整理 区间的概念类似于STL中的容器概念.一个区间提供了可以访问半开放区间[first,one_past_last)中元素的迭代器,还提供了区间中的元素数量的信息. ...

  6. PHP之HMVC

    HMVC(Hierarchical-Model-View-Controller),也可以叫做 Layered MVC.顾名思义,就是按等级划分的 MVC 模式,简单的解释就是把MVC又细分成了多个子 ...

  7. 第四篇、微信小程序-icon组件

    属性: 效果图: test.wxml <!--成功图标--> <icon type="success" size="40"/> < ...

  8. String.Trim

    String.Trim有2个重载方法,分别是:Trim()和Trim(char[]),根据官方的解释 Trim():从当前String对象移除所有前导空白字符和尾部空白字符. Trim(char[]) ...

  9. 《java编程思想》--多线程基础--Runnable

    一.简单说下Runnable是什么 1.它是一个接口 2.只提供了run方法 3.这个接口提供了一个协议:实现这个接口的类是active的(不必成为Thread的子类) 4.run方法没有返回值 /* ...

  10. 【winform】如何在DateTimePicker中显示时分秒

    1. 首先属性里面的Format属性value设置为Custom(默认为Long) 2. 对应的Custom属性value设置为yyyy-MM-dd HH:mm:ss