最近在做CLFS,又遇到了Udev的问题.自己对udev和模块之间加载和被加载,依靠和被依靠的关系一直有点不清楚,这次遇到了就索性搞明白.
作者: Manson.Li
更新日期:2007-9-12
联系方式: lizhilianglove@163.com
转载请注明作者和出处.
本文主要解决的问题是:
1. udev创建设备文件需要事先有设备驱动,而Linux内核默认在打开设备文件的时候加载驱动?那么这个先有鸡还是先有鸡蛋的问题是如何解决的?
2. udev在设计上不是应用在打开设备时候加载设备驱动的,可是start_udev这个tools却能在系统启动的时候加载已经有的设备的驱动并创建其设备文件,其中的原理是?
关于udev的其他一些知识比如说具体应用,rule编写,这里介绍一些网站:
Udev的主网站(英文):
http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
对应的中文翻译:
FQA: 王旭 http://gnawux.blogchina.com
Primer: http://hi.baidu.com/chenzhuoyou/blog/item/fb2f4708bc27e7970a7b8237.html
panjet写的udev介绍: udev轻松上路
>> Linux 高级应用 >> Linux 嵌入技术
1. 一些准备知识
1.1 Sysfs
Sysfs是如何知道当前系统中的设备以及对应的设备号的呢?
Sysfs发现设备是通过kernel启动时候系统初始化进行设备枚举发现的,而对应的设备号就是由对应的驱动注册的,这些驱动即可以是包含在内核里的也
可以是模块的.在驱动没有加载前,系统是能通过VID和POD(Vendor ID/ Product ID)认识设备,但是不能驱动设备的.
现在udevd(守护进程)就能使用驱动注册的设备号信息来创建设备文件了.
1.2 Udev Bootscript
CLFS中提供是s10udev这个 initscript来在Linux启动的时候创建设备.在我看来和start_udev这个tools工具是一样的,这个工具本身也就是一个shell script.
首先取消掉默认的uneven handler:
/sbin/hotplug,因为kernel不再需要这个hotplug了,udevd将通过netlink
socket开监听uevents.然后将在/dev中创建一些静态的设备文件节点,因为这些设备有些不被udev支持,有些又是运行udev的必然前
提.(这边要区别开为内核能正常启动而创建的null和console,目的不同)
1.3 Device Node Create
这边具体讲解udevd是如何通过sys来获得设备的大小设备号的.首先udev在sys中寻找到大小设备号,必然/sys/class/tty/vcs/dev中有”7:0”便是了.根据这个号再到/etc/rules.d中寻找创建规则进行创建.
2. udev和module之间的关系
2.1 Module Loading
被编译成模块的设备驱动可能会有一个基于bus-specific
identifier的别名,这个别名就指明了其支持的设备.可以通过modinfo看到.比如 snd-fm801驱动支持Vendor ID
0x1319,device ID
0x0801的PCI设备,那么它的别名就是“pci:v00001319d00000801sv*sd*bc04sc01i*”对应大多数设备又可以从
sys中找到与这个别名对应的标识.
比如/sys/bus/pci/devices/0000:00:0d.0/modalias中就包含了这样的字符串
“pci:v00001319d00000801sv00001319sd00001319bc04sc01i00”,这样就在设备和驱动之建立了联系.
所以udevd便调用/sbin/midprobe使用上面的这些别名来加载设备的驱动.
好,现在来回答我们的第二个问题: start_udev这个tools是如何在系统启动时候加载设备驱动的?
补充一下:这里指的start_udev和udevstart都是用在fedora下的两个tools,
start_udev实质上就是调用udevstart.如果从tarball编译udev是没有这两个的,取而代之的是: 一个udev脚本,
一个udevtrigger(这个作用和udevstart相同).
在fedora系统中,start_udev将会被在rc.sysinit前调用,也就是kernel执行完后第一程式.这个时候内存中的驱动只有包含在
内核中的或者通过initrd方式加载的. 依然有许多设备虽然系统已经识别到,但是并没有加载驱动.
在这些系统识别到的设备我们就能在/sys下找到对应的设备目录,目录中有一个uevent的文件,其实也就是系统识别到设备时候发出的event事件.
由于在start_udev之前,系统中并没有处理uevents的handler,所以设备对应的模块并没有被加载.
Start_udev开始后首先做的是同1.2 udev
bootscript同样的事情.然后其便开始遍历/sys目录,寻找并试图打开uevent文件.(找到并能打开这个文件就代表有这个设备存在),如果
寻找到就往里面写入”add”,相当于再次触发event事件.
但是这个时候udevd守护进程已经开启,它捕捉到了这个事件,便通过/sys下的modalias获得驱动对应模块的别名,然后调用modprobe加
载.
2.2 udev处理热插拔/动态设备
当你插入一个设备比如说USB Disk,内核发现设备连接并产生一个uevent,这个uevent被udevd捕获并按照上述的方法处理.
3. 不适合上述方法的模块加载情形
Udev只能加载那些有
bus-specific别名,并且bus驱动将必要的设备别名正确的写在sysfs的modalias里面的设备模块.对于其他情况的情况就要用其他方
法了. 这样检查一个模块是否被udev支持也就是通过modinfo看模块的命名并在/sys/bus寻找modalias文件.
那么对于不适合上述条件的module,对于”wrapper”形式的可以通过修改/etc/modprobe.conf 添加“install
module_1 /sbin/modprobe module_2”也就是在安装module_1的时候自动安装module_2.
当然不是”wrapper”形式的,就通过修改开机脚本,手动添加了.(”
wrapper”意思就是说module_1是作为module_2的补充,本身并没有什么意义)
现在回到第一个问题: udev创建设备文件需要事先有设备驱动,而Linux内核默认在打开设备文件的时候加载驱动?那么这个先有鸡还是先有鸡蛋的问题是如何解决的?
Udev创建设备名前是需要驱动的,那么那些符合udev自动加载的模块(实质上是udev调用modprobe)在udevstart中便自动加载好了驱动. 当然其他的设备,如果你在udev创建设备前,没有手动的加载的话,那么是自然不能创建设备文件的了.
阅读(3428) | 评论(1) | 转发(0) |