7.4. 在 LFS 系统上处理设备和模块

第 6 章 中,我们安装了 Udev 包。在我们深入了解其工作原理之前,有必要简要回顾一下以前的设备处理方法。

通常来说,Linux 系统传统上使用一种静态设备创建方法,即在/dev下创建大量设备节点(有时实际上是数千个节点),无论相应的硬件设备是否实际存在。这通常通过一个 MAKEDEV 脚本来完成,该脚本包含许多对 mknod 程序的调用,并为世界上可能存在的每个设备提供相关的设备主设备号和次设备号。使用 Udev 方法,只有内核检测到的设备才会创建设备节点。由于这些设备节点将在每次系统启动时创建,因此它们将被存储在一个tmpfs文件系统上(一个完全驻留在系统内存中的虚拟文件系统)。设备节点不需要太多空间,因此使用的内存可以忽略不计。

7.4.1. 历史

在 2000 年 2 月,一个新的文件系统叫做devfs被合并到 2.3.46 内核中,并在 2.4 系列稳定内核期间可用。虽然它存在于内核源代码本身中,但这种动态创建设备的方法从未获得核心内核开发人员的压倒性支持。

采用的方法的主要问题在于它处理设备检测、创建和命名的方式。后一个问题,即设备节点命名,可能最为关键。人们普遍认为,如果允许设备名称可配置,那么设备命名策略应该由系统管理员决定,而不是由任何特定的开发人员强加给他们。该devfs文件系统还存在其设计中固有的竞争条件,如果不大幅修改内核就无法修复。由于最近缺乏维护,它也被标记为已弃用。devfs随着不稳定的 2.5 内核树的开发,后来发布为 2.6 系列稳定内核,一个新的虚拟文件系统叫做

sysfs应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。是 to export a view of the system's hardrware configuration to userspace processes. With this userspace-visible representation, the possibility of seeing a userspace replacement for应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。became much more realistic.devfs7.4.2. Udev 实现

文件系统在上面被简要提及。有人可能会想应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。如何知道系统上存在的设备以及应该用于这些设备的设备号。直接编译到内核中的驱动程序在被内核检测到时,会将它们的对象注册到应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。。对于编译为模块的驱动程序,此注册将在模块加载时发生。一旦应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。文件系统被挂载(在应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。/sys上),内置驱动程序注册到 的数据就可供用户空间进程和 udev 用于设备节点创建。are available to userspace processes and to udev for device node creation.应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。S10udev init 脚本负责在 Linux 启动时创建这些设备节点。该脚本首先将 /sbin/udevsend 注册为热插拔事件处理程序。热插拔事件(如下所述)通常不会在此阶段生成,但为了防止它们确实发生,会注册 udev。然后 udevstart 程序遍历该

are not usually generated during this stage, but udev is registered just in case they do occur. The udevstart program then walks through the上),内置驱动程序注册到 的数据就可供用户空间进程和 udev 用于设备节点创建。文件系统并在/dev下创建与描述匹配的设备。例如,/sys/class/tty/vcs/dev包含字符串“7:0”。 udevstart 使用此字符串创建/dev/vcswith major number 7 and minor 0. The names and permissions of the nodes created under the/dev目录根据/etc/udev/rules.d/目录中的文件中指定的规则进行配置。这些规则的编号方式与 LFS-Bootscripts 包类似。如果 udev 找不到它正在创建的设备的规则,它将默认权限设置为 660,所有权设置为 root:root

一旦以上阶段完成,所有已经存在并且具有编译到内核中的驱动程序的设备都将可用。 这使我们来到了具有模块化驱动程序的设备。

之前,我们提到了“热插拔事件处理程序。”的概念。当内核检测到新的设备连接时,内核将生成一个热插拔事件并查看文件/proc/sys/kernel/hotplug以确定处理该设备连接的用户空间程序。udev 启动脚本将 udevsend 注册为此处理程序。当生成这些热插拔事件时,内核将告诉 udev 检查上),内置驱动程序注册到 的数据就可供用户空间进程和 udev 用于设备节点创建。文件系统以获取有关此新设备的信息,并为其创建/dev条目。

这使我们想到了 udev 存在的一个问题,以及devfs以前也存在的问题。它通常被称为“鸡和蛋”问题。大多数 Linux 发行版都通过/etc/modules.conf中的条目来处理模块的加载。访问设备节点会导致加载相应的内核模块。使用 udev,此方法将不起作用,因为设备节点在模块加载之前不存在。为了解决这个问题,S05modules 启动脚本以及/etc/sysconfig/modules文件被添加到 LFS-Bootscripts 包中。通过将模块名称添加到modules文件中,这些模块将在计算机启动时加载。这允许 udev 检测设备并创建适当的设备节点。

请注意,在速度较慢的机器上或对于创建大量设备节点的驱动程序,创建设备的过程可能需要几秒钟才能完成。这意味着某些设备节点可能无法立即访问。

7.4.3. 处理热插拔/动态设备

当您插入一个设备,例如通用串行总线 (USB) MP3 播放器时,内核会识别出该设备现在已连接并生成一个热插拔事件。如果驱动程序已经加载(无论是因为它被编译到内核中还是因为它通过 S05modules 启动脚本加载),则将调用 udev 来根据应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。中的可用数据创建相关的设备节点。上),内置驱动程序注册到 的数据就可供用户空间进程和 udev 用于设备节点创建。.

如果刚插入的设备的驱动程序可以作为模块使用,但当前未加载,则 Hotplug 包将加载相应的模块并通过为其创建设备节点来使该设备可用。

7.4.4. 创建设备的问题

在自动创建设备节点时,存在一些已知问题

1) 内核驱动程序可能不会将其数据导出到应运而生。 的工作是向用户空间进程导出系统硬件配置的视图。有了这个用户空间可见的表示,看到一个用户空间替代 的可能性变得更加现实。.

这在来自内核树之外的第三方驱动程序中最为常见。Udev 将无法自动为此类驱动程序创建设备节点。使用/etc/sysconfig/createfiles配置文件手动创建设备。查阅devices.txt文件内的内核文档或该驱动程序的文档以查找正确的设备主设备号/次设备号。

2) 需要非硬件设备。这在高级 Linux 声音体系结构 (ALSA) 项目的开放声音系统 (OSS) 兼容性模块中最常见。这些类型的设备可以通过以下两种方式之一处理

  • 将模块名称添加到/etc/sysconfig/modules

  • /etc/modprobe.conf中使用“install”行。这告诉 modprobe 命令“在加载此模块时,同时加载此另一个模块。” 例如

    install snd-pcm modprobe -i snd-pcm ; modprobe \
        snd-pcm-oss ; true

    这将导致系统在发出任何加载驱动程序 snd-pcm 的请求时加载 snd-pcmsnd-pcm-oss 模块。

7.4.5. 有用的阅读材料

以下站点提供了其他有用的文档