LFS 系统的设备和模块处理

本文介绍了Linux系统中的设备管理和模块处理方式,包括传统的静态设备节点创建方法和现代的udev动态设备节点管理。文章详细解释了udev的工作原理及其如何解决devfs存在的问题。
(uC)linux的驱动程序
• Linux下对外设的访问只能通过驱动程序
• Linux对于驱动程序有统一的接口,以文件的形式
定义系统的驱动程序:
• Open、Release、read、write、ioctl…
• 驱动程序是内核的一部分,可以使用中断、DMA等
操作
• 驱动程序需要在用户态和内核态之间传递数据
• uClinux下可以在应用层直接访问外设,操作寄存
器口,但是无法处理中断——不推荐使用
• uClinux不支持模块加载
内核功能的划分
• 进程管理(进程之间的通讯与同步)
• 内存管理(malloc/free)
• 文件系统
• 设备控制
• 网络功能(网络通讯协议等)
Linux下设备和模块的分类
按照上述系统内核的功能,Linux中把系统
的设备定义成如下三类:
• 字符设备
• 块设备
• 网络设备
Linux下的设备
• Linux的设备以文件的形式存在于/dev目录下
• 设备文件是特殊文件,使用ls /dev -l命令可以
看到:
crw------- 1 root root 10, 7 Aug 31 2002 amigamouse1
crw------- 1 root root 10, 134 Aug 31 2002 apm_bios
brw-rw---- 1 root disk 29, 0 Aug 31 2002 aztcd
主设备号和次设备号
• 主设备号标识设备对应的驱动程序
• 一个驱动程序可以控制若干个设备,次设备号提
供了一种区分它们的方法
• 系统增加一个驱动程序就要赋予它一个主设备
号。这一赋值过程在驱动程序的初始化过程中
int register_chrdev(unsigned int major, const char
*name,struct file_operations *fops);
创建设备节点
• 设备已经注册到内核表中,对于设备的访问通过
设备文件(设备文件与设备驱动程序的主设备号
匹配),内核会调用驱动程序中的正确函数
• 给程序一个它们可以请求设备驱动程序的名字。
这个名字必须插入到/dev目录中,并与驱动程序
的主设备号和次设备号相连
• 使用mknod在文件系统上创建一个设备节点
mknod
/dev/mydevice
c 254 0
动态分配设备号
• 在Documentation/device.txt文件中可以找
到已经静态分配给大部分设备的列表
• 由于许多数字已经分配了,为新设备选择一
个唯一的号码是很困难的
• 如果调用register_chrdev时的major为零,
函数就会选择一个空闲号码并做为返回值返

动态分配的问题
动态分配的主设备号不能保证总是一样的,
无法事先创建设备节点
• 可以从/proc/devices读取
cat /proc/devices
• 利用脚本动态创建设备文件节点
设备管理的问题
如今,Linux 支持很多不同种类的硬件。这
意味着/dev中都有数百个特殊文件来表示所有
这些设备。而且,这些特殊文件中大多数甚至
不会映射到系统中存在的设备上
使用devfs
• 在Linux 2.4的内核里引入了devfs来解决
linux下设备文件管理的问题
• 在驱动程序中通过devfs_register()函数创
建设备文件系统的节点
• 系统启动的时候mount设备文件系统
• 所有需要的设备节点都由内核自动管理。
/dev目录下只有挂载的设备


http://man.ddvip.com/os/LFS-6.1.1/chapter07/udev.html




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

Chapter 6 里,我们安装了 Udev 软件包,在开始深入讨论它如何工作之前,我们先简要回顾一下以前处理设备的方法。

传统上一般 Linux 系统使用创建静态设备的方法,因此在 /dev 目录下创建了大量的设备节点(有时会有数千个节点),而不管对应的硬件设备实际上是否存在。这通常是由 MAKEDEV 脚本完成的,这个脚本包含许多调用 mknod 程序的命令,为这个世界上可能存在的每个设备创建相应的主设备号和次设备号。而使用 udev 方式的时候,只有被内核检测到的设备才为其创建设备节点。因为每次系统启动的时候都要重新创建这些设备节点,所以它们被存储在 tmpfs 文件系统(一种完全存在于内存里,不占用任何磁盘空间的文件系统)上,设备节点不需要很多磁盘空间,所占用的内存可以忽略不计。

7.4.1. 历史

2000 年 2 月的时候,2.3.46 版本的内核引入了一种称为 devfs 的文件系统,在 2.4 系列稳定版本的内核中都是可用的。尽管它存在于内核源代码中,但这种动态创建设备的方法却从未得到核心内核开发者们的全力支持。

devfs 存在的主要的问题是它处理设备检测、创建和命名的方式,其中设备节点的命名可能是最严重的问题。一般可接受的方式是,如果设备名是可配置的,那么设备命名策略应该由系统管理员决定,而不是由某些开发者强制规定。devfs 文件系统还存在竞争条件(race conditions)的问题,这是它天生的设计缺陷,不对内核做彻底的修改就无法修正这个问题。因为近来缺乏维护,它已经被标记为 deprecated(反对的)。

随着非稳定的 2.5 内核树的开发,即后来发布的 2.6 系列稳定版本内核,一种被称为 sysfs 的新虚拟文件系统诞生了。sysfs 的工作是把系统的硬件配置视图导出给用户空间的进程。由于有了这个用户空间可见的表示,代替 devfs 方案的时机就成熟了。

7.4.2. Udev 实现

上面简单的提到了 sysfs 文件系统,您可能想知道 sysfs 是怎么认出系统中存在的设备以及应该使用什么设备号。对于已经编入内核的驱动程序,当被内核检测到的时候,会直接在 sysfs 中注册其对象;对于编译成模块的驱动程序,当模块载入的时候才会这样做。一旦挂载了 sysfs 文件系统(挂载到 /sys),内建的驱动程序在 sysfs 注册的数据就可以被用户空间的进程使用,并提供给 udev 以创建设备节点。

S10udev 初始化脚本负责在 Linux 启动的时候创建设备节点,该脚本首先将 /sbin/udevsend 注册为热插拔事件处理程序。热插拔事件(随后将讨论)本不应该在这个阶段发生,注册 udev 只是为了以防万一。然后 udevstart 遍历 /sys 文件系统,并在 /dev 目录下创建符合描述的设备。例如,/sys/class/tty/vcs/dev 里含有"7:0"字符串,udevstart 就根据这个字符串创建主设备号为 7 、次设备号为 0/dev/vcs 设备。udevstart 创建的每个设备的名字和权限由 /etc/udev/rules.d/ 目录下的文件指定的规则来设置,这些文件以类似于 LFS 启动脚本风格的编号。如果 udev 找不到所创建设备的权限文件,就将其权限设置为缺省的 660 ,所有者为 root:root

上面的步骤完成后,那些已经存在并且已经内建驱动的设备就可以使用了,那么以模块驱动的设备呢?

前面我们提到了"热插拔事件处理程序"的概念,当内核检测到一个新设备连接时,内核会产生一个热插拔事件,并在 /proc/sys/kernel/hotplug 文件里查找处理设备连接的用户空间程序。udev 初始化脚本将 udevsend 注册为该处理程序。当产生热插拔事件的时候,内核让 udev/sys 文件系统里检测与新设备的有关信息,并为新设备在 /dev 里创建项目。

这样带来了 udev 存在的一个问题,之前 devfs 也存在同样的问题。这通常是个"先有鸡还是先有蛋"问题。大多数 Linux 发行版通过 /etc/modules.conf 配置文件来处理模块加载,对某个设备节点的访问导致相应的内核模块被加载。对 udev 这个方法就行不通了,因为在模块加载前,设备节点根本不存在。为了解决这个问题,在 LFS-Bootscripts 软件包里加入了 S05modules 启动脚本,以及 /etc/sysconfig/modules 文件。通过在 modules 文件里添加模块名,就可以在系统启动的时候加载这些模块,这样 udev 就可以检测到设备,并创建相应的设备节点了。

注意,在慢速的机器上,或者对于需要创建大量设备节点的驱动程序,创建设备的过程可能需要好几秒钟,这意味着某些设备节点不能立即访问到。

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

当您插入一个设备,例如一个 USB 接口的 MP3 播放器,内核会检测到设备连接,并产生一个热插拔事件,如果驱动程序已经加载(要么是因为驱动已经编入内核,要么是已经通过 S05modules 启动脚本加载了),udev 将被调用,并根据 /sys 目录下的 sysfs 数据来创建相应的设备节点。如果该设备的驱动是一个未加载的模块,将设备连接到系统上只会让内核的总线驱动产生一个热插拔事件,通知用户空间有新设备连接,但并不加载驱动。事实上,什么都没有做,设备仍然不能使用。

如果刚才插入的设备有一个驱动程序模块但是尚未加载,Hotplug 软件包就有用了,它就会响应上述的内核总线驱动热插拔事件并加载相应的模块,为其创建设备节点,这样设备就可以使用了。

7.4.4. 创建设备的问题

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

1) 某个内核驱动可能没有将其数据导出到 sysfs

这个问题在内核源代码树之外的第三方驱动程序上尤其常见,结果是这些驱动无法创建其设备节点。用 /etc/sysconfig/createfiles 配置文件手动创建这些设备,参考内核文档里的 devices.txt 文件或者该驱动的文档以获得正确的主/次设备号。

2) 需要一个非硬件设备,这个问题通常出现在 ALSA(高级 Linux 声音架构)项目里的 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. 有用的读物

一些有用的补充文档可以在下列网站得到:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值