The Linux Device Model
Many Linux subsystems, such as the /dev filesystem, hotplug, module autoload, and microcode download have undergone significant changes with the introduction of the new device model. Learn about udev, sysfs, kobjects, classes, and more.
The Linux 2.6 kernel features a new device model built around concepts like sysfs, kobjects, device classes, and udev. The new model makes it easier to develop device drivers by introducing C++- like abstractions that distill commonalities from device drivers into bus and core layers. It also weeds policies out of kernel space and pushes them to user space, which has resulted in a total revamp of many features, including /dev node management, hotplug, coldplug, module autoload and firmware download.
This month, let’s look at the different pieces that constiture the device model and how each piece affects key kernel subsystems. But let’s start by learning about udev with the help of some examples.
Tinkering with Udev
Years ago, when Linux was young, it wasn’t fun to administer device nodes. All the needed nodes (which could run into thousands) had to be statically created under the /dev directory. With the advent of the 2.4 kernels came devfs, which introduced dynamic device node creation. Devfs provided kernel interfaces to request generation of device nodes in an in-memory filesystem, but the onus of naming the nodes still rested with device drivers. However, device naming policy is administrative and doesn’t mix well with the kernel. Udev arrived on the scene to push device management entirely to user space.
Udev depends on the following to do its work:
1.Kernel sysfs support, which is an important part of the Linux device model. We’ll look at sysfs later on, but for now, take the corresponding sysfs file accesses for granted.
2.A set of user space daemons and utilities, such as udevd and udevinfo.
3.User-specified rules located in the /etc/udev/rules.d directory. You can write rules to get a consistent view of your devices.
To understand how to use udev, let’s start off with an example. Assume that you have a USB DVD drive and a USB CD-RW drive. Depending on the order in which you hotplug these devices, one of them is assigned the name sr0, while the other gets the name sr1. During pre-udev days, you had to figure out the associated names before you could use the devices. But with udev, you can consistently view the DVD (say, as /dev/usbdvd) and the CD-RW (say, as /dev/usbcdrw) irrespective of the order in which they are plugged in or out.
First, pull product attributes from corresponding files in sysfs. Use udevinfo to collect device information:
$ 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”
…
$ 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”
…
Now let’s use the product information gleaned above to identify the devices and add udev naming rules. Create a file called /etc/udev/rules.d/40-cdvd.rules and add the rules shown in Listing One to it.
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”
The first rule tells udev that whenever it finds a USB device with a product ID of 0×0701, vendor ID of 0×05e3, and a device name starting with sr, it has to create a node of the same name under /dev and produce a symbolic link named usbdvd to the created node. The second rule orders the creation of a symbolic link named usbcdrw for the CD-RW drive.
To test for syntax errors in your rules, run udevtest on /sys/block/sr1. To turn on verbose messages to /var/log/messages, set udev_log to yes in /etc/udev/udev.conf. To repopulate the /dev directory with the newly-added rules, restart udev using udevstart.
Once all of this is done, your DVD will consistently appear as /dev/usbdvd to the system, while your CD-RW drive will always appear as /dev/usbcdrw. Moreover, you can confidently mount them from shell scripts using commands like mount /dev/usbdvd /mnt/dvd.
Consistent naming of device nodes (and network interfaces) is not the sole capability of udev. Indeed, udev has metamorphosed into the Linux hotplug manager as well. Udev is also in charge of automatically loading modules on demand, and downloading microcode onto devices that need them. But before digging into those capabilities, let’s get a basic understanding of the innards of the device model.
Kobjects, Sysfs, and Device Classes
Kobjects, sysfs, and device classes are the building blocks of the device model, but are publicity shy and prefer to remain behind the scene. Each is almost exclusively in the usage domain of bus and core implementations, and hide inside APIs that provide services to device drivers.
Kobjects introduce an encapsulation of common object properties, like usage reference counts. They are usually embedded inside larger structures. If you look at the definition of a kobject in include/linux/kobject.h, you’ll notice two interesting fields:
1.A pointer to a kset, which is an object set to which the kobject belongs.
2.A ktype, which is an object type that describes the kobject.
Kobjects are intertwined with an in-memory filesystem called sysfs, which is mounted under /sys at boot time (look at /etc/fstab). Every kobject instantiated within the kernel has a representation inside sysfs. Sysfs is similar to the process filesystem (procfs) in that both are in-memory filesystems containing information about kernel data structures. While procfs is a generic window into kernel internals, sysfs is specific to the device model. Sysfs is hence not a replacement for procfs- information such as sysctl parameters and process descriptors belong to procfs and not sysfs.
Browse through /sys looking for entries that associate with say, your network card, to get a feel for its hierarchical organization. As will be apparent when you read the rest of this article, udev depends on sysfs for most of its extended functions. Sysfs is also the user space manifestation of the kernel’s structured device model.
The concept of device classes is another feature of the device model, and is an interface that you’re more likely to use in your device driver than the others. The class interface abstracts the idea that each device falls under a broader class (or category) of devices. A USB mouse, a PS/2 keyboard, and a joystick, all fall under the input class and own entries under /sys/class/input/.
The device class programming interface is built on top of kobjects and sysfs, so it’s good place to start digging to understand the end-to-end interactions between the components of the device model. Let’s take the Real Time Clock (RTC) driver as an example. The RTC driver is a miscellaneous (or “misc”) driver. Misc drivers are simple character drivers that have common characteristics.
First, let’s insert the RTC driver module and look at the nodes created in /sys and /dev:
$ modprobe rtc
$ 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
$ ls –l /dev/rtc
crw-r–r– 1 root root 10, 135 Jan 15 01:23 /dev/rtc
/sys/class/misc/rtc/dev contains the major and minor numbers assigned to this device; /sys/class/misc/rtc/uevent is used for coldplugging (discussed later), while /dev/rtc is used by applications to access the RTC driver.
Now let’s understand the code flow through the device model. Misc devices utilize the services of misc_register() during initialization, which looks like Listing Two if you strip off some code:
/* … */
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;
}
/* … */
Figure One continues to peel off more layers to get to the bottom of the device modeling. It illustrates the transitions that ripple through classes, kobjects, sysfs and udev, which result in the generation of the /sys and /dev files listed above.
The Bus-Device-Driver Model
Another abstraction that is part of the device model is the bus/device/driver programming interface. Kernel device support is structured cleanly into buses, devices, and drivers. This renders the individual driver implementations simpler and more general. Bus implementations can, for example, search for drivers that can handle a particular device.
Consider the kernel Inter-Integrated Circuit (I2C) subsystem. The I2C core layer registers each detected I2C bus adapter using bus_register(). When an I2C client device, say an EEPROM, is probed and detected, its existence is recorded via device_register(). Finally, the I2C EEPROM client driver registers itself using driver_register().
bus_register() adds a corresponding entry to /sys/bus/, while device_register() adds entries under sys/devices/. struct bus_type, struct device, and struct device_driver are the main datastructures used respectively by buses, devices and drivers. Take a peek inside include/linux/device.h for their definitions.
0
上一篇:从Linux内核中提取的链表封装
下一篇:没有了
下一篇:没有了
最新评论共有 0 位网友发表了评论
查看所有评论
发表评论
热点关注
- 深入理解LINUX内核中文版
- Linux内核下载
- 全面的framebuffer详解
- linux ioctl()函数
- Linux 2.6 字符设备驱动程
- linux内核IOCTL网络控制框
- Linux重新编译内核指南
- Linux编译内核详解
- 升级linux内核到2.6.24
- Linux内核编程实战经验谈
- Linux 2.6.16 udev问题
- linux2.6内核下的一个按键
- kmalloc, vmalloc分配的内
- Linux 2.6内核的编译步骤
- linux 内核升级和系统引导
- 如何编译Linux的内核
- linux kernel API文档
- 2.4内核编译详解
- Linux操作系统源代码详细
- 升级RedHat9.0(Kernel2.4.

