udev研究之与模块关系

来源:互联网 发布:淘宝5星好评语 编辑:程序博客网 时间:2024/06/07 09:45

最近在做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轻松上路

        www.linuxforum.net/forum >> 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创建设备前,没有手动的加载的话,那么是自然不能创建设备文件的了.

文章出处:飞诺网(http://www.diybl.com/course/6_system/linux/Linuxjs/200868/123630.html)