《Linux From Scratch》第三部分:构建LFS系统 第七章:基本系统配置- 7.3. LFS 系统中的设备和模块管理

 在 第六章, 我们通过 systemd 的源码包安装好了
udev。在开始了解它是如何工作之前,我们先来简要的回顾下以前处理设备的方法。

传统的 Linux 不管硬件是否真实存在,都以创建静态设备的方法来处理硬件,因此需要在 /dev 目录下创建大量的设备节点文件(有时会有上千个)。这通常由
MAKEDEV
脚本完成,它通过大量调用 mknod
程序为这个世界上可能存在的每一个设备建立对应的主设备号和次设备号。

而使用 udev
方法,只有当内核检测到硬件接入,才会建立对应的节点文件。因为需要在系统启动的时候重新建立设备节点文件,所以将它存储在
devtmpfs
文件系统中(完全存在于内存中的虚拟文件系统)。设备节点文件无需太多的空间,所以占用的内存也很小。

7.3.1. 历史

2000 年 2 月,一种名叫 devfs
的文件系统被合并到 2.3.46 内核版本,2.4 系列的稳定内核中基本可用。尽管它存在于内核的源代码中,但是这种动态创建设备的方法却从来都得不到核心内核开发者的大力支持。

问题存在于它处理设备的检测、创建和命令的方式,其中最大的问题莫过于它对设备节点的命名方式。大部分开发者的观点是,设备的命名应该由系统的所有者决定,而不是开发者。
devfs
存在一个严重的设计缺陷:它存在严重的 race conditions
问题,如不对内核做大量的修改就无法修正这一问题。最终,因为缺乏有效的维护,在 2006 年 6 月终被移出内核源代码。

再后来,随着非稳定的 2.5 版本的内核开发,到稳定的 2.6 内核,又出现了一种全新的虚拟文件系统
sysfssysfs
的工作是将系统的硬件配置导入到用户空间进程。通过对用户空间可视化的改善,代替devfs 变得更加现实。

7.3.2. Udev 实现

7.3.2.1. Sysfs

上文简单的提及了 sysfs
文件系统。有些人可能会问,sysfs
到底是如何知道当前系统有哪些设备,这些设备又该使用什么设备号呢。对于那些已经编译进内核的设备,会在内核检测到时直接注册为
sysfs 对象(devtmpfs
内建)。对于编译为内核模块的设备,将会在模块载入的时候注册。一旦
sysfs 文件系统挂载到 /sys,已经在
sysfs 注册的硬件数据就可以被用户空间的进程使用,
udevd 也就能够处理了(包括对设备节点进行修改)。

7.3.2.2. 设备节点的创建

设备文件是通过内核中的 devtmpfs
文件系统创建的。任何想要注册的设备都需要通过 devtmpfs
(通过驱动程序核心)实现。每当一个 devtmpfs
实例挂载到 /dev,就会建立一个设备节点文件,它拥有固定
的名称、权限、所有者。

很短的时间之后,内核将给 udevd
一个 uevent。基于 /etc/udev/rules.d/lib/udev/rules.d/run/udev/rules.d 目录内文件指定的规则,udevd
将会建立到设备节点文件的额外符号链接,这有可能更改其权限,所有者,所在组,或者是更改 udevd 内建接口(名称)。

这三个目录下的规则都像 LFS-Bootscripts 包那样标有数字,所有三个目录都会统一到一起。如果
udevd 找不到和所创建设备相应的规则,它会保留
devtmpfs 里初始化时使用过的权限和属主。

7.3.2.3. 加载模块

编译成模块的设备驱动可能会包含别名。别名可以通过
modinfo
打印出来查看,一般是模块支持的特定总线的设备描述符。举个例子,驱动
snd-fm801
支持厂商 ID 为 0x1319 以及设备 ID 为 0x0801 的设备,它包含一个
“pci:v00001319d00000801sv*sd*bc04sc01i*”
的别名,总线驱动导出该驱动别名并通过 sysfs
处理相关设备。例如,文件 /sys/bus/pci/devices/0000:00:0d.0/modalias
应该会包含字符串 “pci:v00001319d00000801sv00001319sd00001319bc04sc01i00”。Udev
采用的默认规则会让 udevd 根据 uevent 环境变量
MODALIAS 的内容(它应该和 sysfs 里的 modalias 文件内容一样)调用
/sbin/modprobe,这样就可以加载在通配符扩展后能和这个字符串一致的所有模块。

在这个例子里,意味着,除了 snd-fm801 之外,一个已经废弃的(不是我们所希望的)驱动
forte 如果存在的话也会被加载。下面有几种可以避免加载多余驱动的方式。

内核本身也能够根据需要加载网络协议,文件系统以及 NLS 支持模块。

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

在你插入一个设备时,例如一个通用串行总线(USB)MP3 播放器,内核检测到设备已连接就会生成一个 uevent。这个 uevent 随后会被上面所说的 udevd 处理。

7.3.3. 加载模块和创建设备时可能碰到的问题

在自动创建设备节点时可能会碰到一些问题。

7.3.3.1. 内核模块没有自动加载

Udev 只会加载包含有特定总线别名而且已经被总线驱动导出到 sysfs 下的模块。在其它情况下,你应该考虑用其它方式加载模块。采用 Linux-3.19,Udev 可以加载编写合适的 INPUT、IDE、PCI、USB、SCSI、SERIO 和 FireWire 设备驱动。

要确定你希望加载的驱动是否支持 Udev,可以用模块名字作为参数运行 modinfo。然后查看 /sys/bus 下的设备目录里是否有个 modalias 文件。

如果在 sysfs 下能找到 modalias 文件,那么就能驱动这个设备并可以直接操作它,但是如果该文件里没有包含设备别名,那意味着这个驱动有问题。我们可以先尝试不依靠 Udev 直接加载驱动,等这个问题以后解决。

如果在 /sys/bus 下的相应目录里没有 modalias 的话,意味着内核开发人员还没有为这个总线类型增加 modalias 支持。使用 Linux-3.19 内核,应该是 ISA 总线的问题。希望这个可以在后面的内核版本里得到解决。

Udev 不会尝试加载类似 snd-pcm-oss 这样的“封装”驱动,也不会加载类似 loop 这样的非硬件驱动。

7.3.3.2. 内核驱动没有自动加载,Udev 也没有尝试加载

如果是 “封装” 模块只是强化其它模块的功能(比如,snd-pcm-oss 模块通过允许 OSS 应用直接访问声卡的方式加强了 snd-pcm 模块的功能),需要配置 modprobe 在 Udev 加载硬件驱动模块后再加载相应的封装模块。可以在任意 /etc/modprobe.d/<filename>.conf文件里增加一行 “softdep”,例如:

softdep snd-pcm post: snd-pcm-oss

请注意 “softdep” 也支持 pre: 的依赖方式,或者混合 pre:post:。查看 modprobe.d(5) 手册了解更多关于 “softdep” 语法和功能的信息。

如果问题模块不是一个封装而且也是有用的,配置 modules 开机脚本在引导系统的时候加载模块。这样需要把模块名字添加到 /etc/sysconfig/modules 文件里的单独一行。这个也可以用于封装模块,但是只是备用方式。

7.3.3.3. Udev 加载了一些无用模块

要么不要编译该模块,或者把它加入到模块黑名单 /etc/modprobe.d/blacklist.conf 里,像下面的例子里屏蔽了 forte 模块:

blacklist forte

被屏蔽的模块仍然可以用 modprobe 强行加载。

7.3.3.4. Udev 创建了错误的设备节点,或错误的软链接

这个情况通常是因为设备匹配错误。例如,一条写的不好的规则可能同时匹配到 SCSI 磁盘(希望加载的)和对应厂商的 SCSI 通用设备(错误的)。找出这条问题规则,并通过 udevadm info 命令的帮助改得更具体一些。

7.3.3.5. Udev 规则工作不可靠

这可能是上个问题的另一种表现形式。如果不是,而且你的规则使用了 sysfs 特性,那可能是内核时序问题,希望在后面版本内核里能解决。目前的话,你可以暂时建立一条规则等待使用的 sysfs 特性,并附加到 /etc/udev/rules.d/10-wait_for_sysfs.rules 文件里(如果没有这个文件就创建一个)。如果你碰到这种情形请通知 LFS 开发邮件列表,这个对我们有帮助。

7.3.3.6. Udev 没有创建设备

后面的内容会假设驱动已经静态编译进内核或已经作为模块加载,而且你也已经确认 Udev 没有创建相应的设备节点。

如果内核驱动没有将自己的数据导出到 sysfs 里,Udev 就没有相关信息来创建设备节点。这通常发生在内核树之外的第三方驱动里。我们可以使用合适的主/副设备数字 ID(查看内核文档里或第三方驱动厂商提供的文档里的 devices.txt 文件) 在 /lib/udev/devices 目录里创建一个静态设备节点。这个静态设备节点随后会被 udev 引导脚本复制到 /dev 里。

7.3.3.7. 设备名称顺序在重启后随机改变

这是因为 Udev 被设计成并行处理 uevents 并加载模块,所以是不可预期的顺序。这个不会“修复”。你不应该依赖稳定的内核模块名称。而是,在检测到设备的稳定特征,比如序列号或 Udev 安装的一些 *_id 应用的输出,来判断设备的稳定名称,之后创建自己的规则生成相应的软链接。可以参考 7.4, “创建自定义符号链接到设备”7.2, “通用网络设置”

7.3.4. 有用的读物

点击以下链接可以获得一些额外的帮助文档:

创建者:Gerard Beekmans

编辑者:Matthew Burgess 和 Armin K.

翻译团队:LCTT

译者/校对:zpl1025,wxy,dongfengweixiao,ictlyh

原文链接

时间: 2024-11-08 19:48:42

《Linux From Scratch》第三部分:构建LFS系统 第七章:基本系统配置- 7.3. LFS 系统中的设备和模块管理的相关文章

Welcome to Linux From Scratch!

/**************************************************************************** * Welcome to Linux From Scratch! * 说明: * 这里主要是想知道LFS项目的一些情况,想知道LFS到底包括哪些内容. * * 2016-3-17 深圳 南山平山村 曾剑锋 *********************************************************************

《Linux From Scratch》第三部分:构建LFS系统 第九章:尾声- 9.4. 接下来做什么呢?

         十分感谢你耐心的阅读这本 LFS 书,我们十分期待本书能够为你构建系统带来一点点的帮助. 我猜,你现在一定很开心--LFS 系统已经安装完成.但是,下面该作些什么呢?不用担心,我们早已经帮你准备好以下这些有益的信息了! 维护 定期检查软件的 bug 和安全公告.因为在从源码构建出 LFS 之后,你便应该养成经常去查看这些报告的好习惯.有关查询的去处,网上倒是有一些不错的资源,这里列举几个: CERT (计算机应急响应小组) CERT 有一个邮件列表,专门公示各种操作系统和应用程

《Linux From Scratch》第三部分:构建LFS系统 第九章:尾声- 9.1. 最后的最后

         哈哈,干的很不错!到这里,全新的 LFS 系统就已经安装完成了!我们也很期待你那闪闪发光的定制 Linux 系统呐. 创建一个 systemd 所需的 /etc/os-release 文件: cat > /etc/os-release << "EOF" NAME="Linux From Scratch" VERSION="7.7-systemd" ID=lfs PRETTY_NAME="Linux F

《Linux From Scratch》第三部分:构建LFS系统 第八章:让LFS系统可引导 - 8.4. 使用 GRUB 设置启动过程

 8.4.1. 简介 警告 对 GRUB 进行错误的配置可能会导致在没有外置启动设备(某些USB设备,某些 CD-ROM 等)的情况下无法正常的启动.你可能仅仅需要修改当前正在使用的引导器(比如:Grub-Legacy,GRUB2 或 LILO 等)的配置. 一定要确保你有一个可以引导的光盘或者是 U 盘以备不时之需,否则万一电脑真的不能启动谁都救不了你.如果你需要建立可引导的设备,可以按照以下方法操作(跳转到 BLFS 从 libisoburn 软件包安装 xorriso). (译者注:其实你

《Linux From Scratch》第一部分:介绍 第一章:介绍-1.1 如何构建LFS系统

         LFS 系统需要在一个已经安装好的 Linux 发行版(比如 Debian.OpenMandriva.Fedora 或 OpenSUSE)中构建.这个已有的 Linux 系统(即宿主)作为构建新系统的起始点,提供了必要的程序,包括一个编译器.链接器和 shell.请在安装发行版的过程中选择 "development(开发)"选项以便使用这些开发工具. 除了将一个独立发行版安装到你的电脑上之外,你也可以使用商业发行版的 LiveCD. 本书的第二章描述了如何创建一个的新

《Linux From Scratch》第二部分:准备构建 第四章:最后的准备- 4.3. 添加 LFS 用户

         当以 root 用户登录时,犯一个小错误可能会破坏或摧毁整个系统.因此,我们建议在本章中以非特权用户编译软件包.你可以使用你自己的用户名,但要容易的话,就建立一个干净的工作环境,创建一个名为 lfs 的新用户作为新组(名字也是 lfs )的成员,并在安装过程中使用这个用户.以 root 用户运行以下命令来添加新用户: groupadd lfs useradd -s /bin/bash -g lfs -m -k /dev/null lfs 命令行选项的意思: -s /bin/ba

《Linux From Scratch》第二部分:准备构建 第五章:构建临时文件系统- 5.10. GCC-4.9.2 - 第2遍

GCC 软件包包含 GNU 编译器集合,其中有 C 和 C++ 编译器. 大概编译时间: 7.7 SBU 所需磁盘空间: 2.6 GB 5.10.1. 安装 GCC 我们第一次编译 GCC 的时候安装了一些内部系统头文件.其中的一个 limits.h 会反过来包括对应的系统头文件 limits.h, 在我们的例子中,是 /tools/include/limits.h.但是,第一次编译 gcc 的时候 /tools/include/limits.h 并不存在,因此 GCC 安装的内部头文件只是部分

What is Cross Linux From Scratch?

/**************************************************************************** * What is Cross Linux From Scratch? * 说明: * 本文想知道交叉编译的LFS到底是什么. * * 2016-3-23 深圳 南山平山村 曾剑锋 ***************************************************************************/ 参考文章

《Linux From Scratch》第四部分:附录- 附录 A. 缩略词和术语

ABI Application Binary Interface 应用程序二进制接口 ALFS Automated Linux From Scratch 自动化 LFS API Application Programming Interface 应用程序设计接口 ASCII American Standard Code for Information Interchange 美国信息交换标准代码 BIOS Basic Input/Output System 基本输入/输出系统 BLFS Beyo