Udev 使用Udev: 1、首先从sysfs的相关文件中获取文件属性。假设DVD:/dev/sr0,CD-RW:/dev/sr1。使用udevinfo来收集设备信息。bash> udevinfo -a -p /sys/block/sr0 Code View: bash> udevinfo -a -p /sys/block/sr0 ... looking at the device chain at '/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4': BUS=?usb? ID=?1-4? SYSFS{bConfigurationValue}=?1? ... SYSFS{idProduct}=?0701? SYSFS{idVendor}=?05e3? SYSFS{manufacturer}=?Genesyslogic? SYSFS{maxchild}=?0? SYSFS{product}=?USB Mass Storage Device? ... bash> udevinfo -a -p /sys/block/sr1 ... looking at the device chain at '/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-3': BUS=?usb? ID=?1-3? SYSFS{bConfigurationValue}=?2? ... SYSFS{idProduct}=?0302? SYSFS{idVendor}=?0dbf? SYSFS{manufacturer}=?Addonics? SYSFS{maxchild}=?0? SYSFS{product}=?USB to IDE Cable? ... 2、使用收集的产品信息来辨别设备并加入udev命名规则,创建一个/etc/udev/rules.d/40-cdvd.rules并加入如下规则: BUS="usb", SYSFS{idProduct}="0701", SYSFS{idVendor}="05e3", KERNEL="sr[0-9]*", NAME="%k", SYMLINK="usbdvd" BUS="usb", SYSFS{idProduct}="0302", SYSFS{idVendor}="0dbf", KERNEL="sr[0-9]*", NAME="%k", SYMLINK="usbcdrw" 规则1的意思是:无论何时它发现一个产品id为0x0701,vender ID是0x05e3,而且名字以sr开头的usb设备,都会在/dev下创建一个同名的节点,并produce一个命名为usbdvd的符号链接给那个节点。 为了测试您规则中的语法错误,在/sys/block/sr*上运行udevtest。为了打开/var/log/messages的verbose messages,设置/etc/udev/udev.conf中的udev_log为"yes".为使新加入的规则在/dev下生效,使用udevstart重启udev,然后您的dvd驱动会标识为/dev/usbdvd。您可以使用mount /dev/usbdvd /mnt/dvd来挂载。 udev的其他功能:Linux热插拔管理、自动按需加载模块、下载微代码到需要的设备。 Sysfs, Kobjects,and Device Classes 一般用于bus和内核实现领域,隐藏在提供给设备驱动的API服务中。 sysfs是内核架构设备模型的用户空间实现,和procfs一样都是内存文件系统,包含了内核数据结构的相关信息。procfs是内核的一般性质的窗口,而sysfs则专注于设备模型。sysfs不是用于替代procfs,因为进程描述符信息和sysctl参数都属于procfs,而非sysfs。udev依赖于sysfs实现大部分功能。 kobjects常嵌入在大的结构体里面,主要包括kref(参数计数管理,kref_init初始化,kref_get()增加计数,kref_put()减少计数,并在计数为0的时候释放kobject),指向所属kset的指针,kobj_type(描述kobject类型);kobjects与sysfs密切相关,每个内核instantiated的kobject都有一个sysfs representation。 设备类是驱动中能用到的另一个接口,类接口抽象了认为每一个设备都会属于一个设备类中,如usb鼠标、PS/2键盘等属于输入类,而且在/sys/class/input/下拥有接口。
类编程接口建立在kobjects和sysfs之上,让我们来看一下RTC: bash> modprobe rtc bash> ls -lR /sys/class/misc drwr-xr-x 2 root root 0 Jan 15 01:23 rtc /sys/class/misc/rtc: total 0 -r--r--r-- 1 root root 4096 Jan 15 01:23 dev --w------- 1 root root 4096 Jan 15 01:23 uevent bash> ls -l /dev/rtc crw-r--r-- 1 root root 10, 135 Jan 15 01:23 /dev/rtc /sys/class/misc/rtc/dev包含了设备的主次设备号,/sys/class/misc/rtc/uevent用于coldplugging,/dev/rtc被应用程序用于访问RTC驱动。Misc驱动使用misc_register()初始化,里面的代码和下面的类似: /* ... */ dev = MKDEV(MISC_MAJOR, misc->minor); misc->class = class_device_create(misc_class, NULL, dev, misc->dev, "%s", misc->name); if (IS_ERR(misc->class)) { err = PTR_ERR(misc->class); goto out; } /* ... */ 下图展示了在classes、kobjects、sysfs和udev之间的转换,最终导致了/sys和/dev里面的文件的产生。 另外一个好的抽象是bus-device-driver编程接口。以I2C为例,I2C核心层对监测到的每一个I2C总线适配器使用bus_register()注册,当I2C客户端设备如EEPROM被监测到时,由device_register()注册,最终I2C EEPROM客户端驱动程序使用driver_register()注册自身,这些注册直接使用I2C核提供的服务。bus_register()会在/sys/bus增加入口,device_register()在/sys/devices下增加入口,struct bus_type,struct device,struct device_driver是主要使用的数据结构。 Hotplug和Coldplug 在系统运行时动态接入的设备叫热插拔设备,而在系统启动前就事先接入的叫冷插拔设备。在以前内核使用在/proc中注册的辅助程序通知用户空间有设备接入,而现在当内核监测到热插拔时,它们使用netlink sockets向用户空间发送uevents。netlink是内核和用户空间通信的有效工具,在用户空间管理设备节点创建和删除的udevd接收到uevents并管理hotplug。以下是热插拔的发展历程:
1、在初始化时,驱动唤醒request_firmware(..,"ipw2100-1.3.fw",..); 2、这dispatch一个热插拔uevent to用户空间,along with the identity of the requested microcode image。 3、Udevd接收到uevent并responds by invoking /sbin/firmware_helper,对于这点,它使用如下在/etc/udev/rules.d/下面的类似的规则:ACTION=="add", SUBSYSTEM=="firmware", RUN="/sbin/firmware_helper" 4、/sbin/firmware_helper进入/lib/firmware/并且定位微代码Image ipw2100-1.3.fw。它dumps the image to /sys/class/0000:02:02.0/data(0000:02:02是PCI bus:device:function,是WiFi卡的标记); 5、驱动接收到微代码并且把它下载到设备,当完成后,它调用release_firmware()来释放相应的数据结构。 6、驱动执行剩下的初始化和WiFi适配器。 Module Autoload 自动按需下载内核模块是Linux支持的有效特性,为理解内核如何发出"module fault"并且udev如何处理它,让我插入Xircom CardBus Ethernet adapter into a laptop's PC Card slot: 1、在编译时,对所支持设备的辨别就作为驱动模块对象的一部分产生,如drivers/net/tulip/xircom_cb.c下的:
这声明了该驱动支持任意PCI vender ID为0x115D和PCI device ID为0x0003的卡,当您安装了该驱动模块后,depmod工具查看module image并且解释在device table里面的ID,然后将下面的entry加入 /lib/modules/kernel-version/modules.alias:alias pci:v0000115Dd00000003sv*sd*bc*sc*i* xircom_cb,这里v表示VenderID,d代表DeviceID,sv代表subvenderID,*代表通配。
2、当您在CardBus插槽中热插拔Xircom card时,内核产生一个uevent声称对新插入设备的辨认。您可以使用udevmonitor来查看产生的uevent: bash> udevmonitor --env 3、Udevd经netlink socket接收到uevent,并唤醒modprobe with 上述的内核传递给它的MODALIAS。 modprobe pci:v0000115Dd00000003sv0000115Dsd00001181bc02sc00i00 4、modprobe在/lib/modules/kernel-version/modules.alias中发现相符的entry,并进而插入xircom_cb: 现在该card就可以上网冲浪了。 一部分不支持在嵌入式设备上使用Udev的原因:
|
|