我的理解是该/sys
目录包含解释有关不同设备的信息的文件。该目录如何以及何时被填充?
例如,在这里探索 Linux 系统,我看到该/sys/bus/i2c/devices
目录包含一些 I2C 设备的文件。
在这种情况下,I2C 设备驱动程序/模块的工作是在那里创建这些文件吗?
那么关于/dev
目录,设备驱动程序/模块是否也填充该目录?提前致谢。
答案1
挂载的文件系统/sys
是sysfs
文件系统。sysfs
是一个所谓的例子虚拟文件系统或者伪文件系统。这些文件系统被称为“虚拟”,因为它们实际上并不代表物理存储的文件,而是合成非文件数据结构的类似文件的视图。
因此,sysfs
它是一个文件系统,它综合了内核内部的类似文件的视图。
每个驱动程序/模块的工作是将其自身及其数据结构注册到内核对象模型,以便内核的其余部分可以“理解”这些数据结构。但是,将这个对象模型转换为 中的目录和文件通常不是驱动程序的工作sysfs
,该工作是由驱动程序sysfs
本身执行的。仅对于特定于设备的信息,模块才必须告知sysfs
如何表示它。
最著名和最古老的虚拟文件系统示例是procfs
文件系统,它通常安装在/proc
.procfs
于 1984 年首次在 Unix V8 中实现。从那时起,它于 1991 年被移植到 SVR4,它激发了 Plan 9 中更全面的实现,该计划又被复制到 4.4BSD 中。有趣的是,FreeBSD 和 OpenBSD 都已逐步淘汰procfs
,而 macOS 则从未拥有过它。
Linuxprocfs
于 1992 年获得了 A。传统上,在 Linux 中,procfs
用于将各种不同的数据导出到用户空间,而不是使用与进程相关的数据。然而,很长一段时间以来,没有一个标准来管理这些数据的公开方式,因此您可以找到各种各样不同的风格:一些数据以易于人类可读的方式公开,但很难被理解。使用脚本进行解析,其他优化为机器可读。一些复杂的数据表示为单个大文件,其他数据表示为每个组成部分一个文件的目录。
sysfs
是为了清理这个混乱而引入的,它对数据的表示方式有严格的规则。
关于/dev
,有一个不同的故事。传统上,/dev
它只是根文件系统上的一个普通目录。系统管理员负责使用该mknod
实用程序创建设备节点。随着时间的推移,Unix 发行版将开始提供系统管理员可以运行的预制脚本来创建最重要的设备节点,甚至更进一步,Unix 发行版的安装程序将使用常用的设备节点预先填充目录,所以一般来说,系统管理员不需要手动创建它们。
随着对热插拔设备的支持不断增加(特别是在引入 USB 和 Firewire 之后),以及 Linux 越来越多地进入通常没有经验丰富的“系统管理员”的市场(例如消费者台式机),很明显,无论是每当您插入或拔出设备时,系统管理员都会手动创建和删除设备节点,为每个可能的设备预先创建每个设备节点也不是一个可行的选择。
因此,devfs
创建了一个虚拟文件系统,它自动包含内核发现的每个设备的设备节点。有一段时间,devfs
通过尝试检测设备并运行脚本来创建设备节点来处理即插即用的特定于发行版的方法并存。
有人对 的质量和实施方式提出了一些批评devfs
。最值得注意的是,有人批评实际上根本不需要创建和删除要在内核内部处理的设备节点,并且这devfs
一点是在 Linux 开发人员开始努力的时候出现的。消除来自内核的东西并不是绝对需要存在的。
Linux 内核开发的信条之一是“机制可以在内核中,策略必须在用户空间中”,但devfs
它违反了这一点,因为它将决策内核中的“我应该给这个设备起什么名字”。
结果,udev
就被开发出来了。udev
由多个组件组成,最重要的是,一个守护进程使用sysfs
(以及一些其他资源,例如udev事件)以了解系统中可用设备的任何更改,然后使用一组用户可定义的规则创建和删除相应的设备节点。这不需要内核的任何特殊支持,因为信息udev
需求已经在sysfs
其他地方可用,并且/dev
可以再次只是一个普通的文件系统。
如今,大多数 Linux 发行版都使用udev
,但也使用udev
已经开发的替代方案,例如eudev
( 的分支udev
)或(基于 BusyBox 的mdev
最小替代品,旨在用于轻量级资源受限系统)。udev
这是将功能从内核移至用户空间的一大优势:一般来说,内核中的某一功能只能有一个实例,而在用户空间中很容易出现相互竞争的实现:可以轻松更换。一般来说,竞争会带来更好的质量。
通常,在使用时udev
,临时文件系统用于/dev
:这样,您不必担心系统崩溃或重新启动后清理陈旧的设备节点:因为您总是从空文件系统开始,udev
只会重新创建实际存在的设备的设备节点。
您可以使用根文件系统并简单地删除启动脚本中某处的内容/dev
(尽管这会变得很棘手,因为您还需要至少一些工作设备节点来/dev
启动)或者您可以使用tmpfs
(仅存在于内存中),您可以在其中使用有同样的问题。
为了解决udev
当您至少需要一些设备节点才能udev
工作但又udev
是创建设备节点的设备节点时如何开始工作的引导问题,devtmpfs
开发了这一问题。
Now,在某种意义上,devtmpfs
与 非常相似devfs
,所以你可能会问自己,为什么被devtmpfs
接受而devfs
没有被接受?嗯,有两个重要的区别:一个提示已经在名称“ devtmpfs
”中。devtmpfs
正在构建:既然已经为您解决了问题tmpfs
,为什么您要重新发明如何在 RAM 中表示文件? tmpfs
(这是针对 的另一个批评devfs
,它重复了 中已经存在的一堆功能tmpfs
。)
另一个区别是它devtmpfs
创建设备节点的方式非常简单,并将更复杂的事情留给了udev
.例如,devtmpfs
不会尝试实现任何复杂的设备命名规则,它只是使用非常简单的名称,然后udev
可以使用其用户定义的规则集创建从用户定义的名称到内核定义的名称的符号链接。
因此,在现代 Linux 系统中,您通常会devtmpfs
安装在/dev
其中创建一些准系统设备节点,您将sysfs
安装在/sys
其中将内核的内部信息公开为文件,并且您udev
在用户空间中运行,该空间接收来自kernel viasysfs
和 udev 事件,并根据用户定义的规则创建到这些准系统设备的链接。
有一个很多更重要的是,这是 10000 公里的概述。
答案2
/sys
内容由内核文件系统驱动程序填充sysfs
。一些通用节点是在注册驱动程序或设备时自动创建的,一些特定于驱动程序和设备的节点是由设备驱动程序本身创建的。
/dev
大多数现代系统上的内容是由udev
用户空间中的框架维护的,它通常是包的一部分systemd
。udev
对于嵌入式系统,还有其他选择,例如mdev
。但内核还提供了对devtmpfs
文件系统的支持,该文件系统减少了功能并用作udev
基础。