Linux unified Device Model
Introduction
The linux2.6 Kernel provides a new device model to uniformly represent and operate all devices on the computer, including the connection relationship between the device and the device. This model is obtained during the analysis of the PCI and USB bus drivers. These two bus types can represent the majority of device types in the current system, they both have sound hot and straight-up mechanisms and support for power management, as well as support for cascading mechanisms, supports more PCI/USB devices in the form of a bridge PCI/USB bus controller. [2] in general, the Linux unified device model has the following features,
* Minimize code duplication
* Provides a unified mechanism such as reference count.
* You can list all the devices in the system, observe their statuses, and view the connected bus.
* The entire device structure in the system can be fully and effectively displayed in the form of a tree-including all bus and internal connections
* The device can be associated with its corresponding driver, and vice versa.
* Devices can be classified by type. For example, devices can be classified as input devices without understanding the topological structure of physical devices.
* The leaf of the device tree can traverse the direction of its root to ensure that the power supply of each device is disabled in the correct order.
The last point is the initial motivation for implementing the device model. If you want to implement Intelligent Power Management in the kernel, you need to establish a tree structure that represents the topological relationship between devices in the system [2]. For example, in a typical PC system, the central processor (CPU) can directly control the PCI bus device, while the USB bus device is a PCI device (PCI-USB Bridge) is connected to the PCI bus device, and the external USB device is connected to the USB bus device. When the computer performs the suspend operation, the Linux kernel should notify each device to suspend power supply in the order of "external USB device-> USB Bus Device-> PCI bus device"; execute resume) otherwise, the device will not be notified of the correct power status change and will not work properly [1].
Key data structure of kernel object mechanism
Kobject Kernel Object
Kobject is a new device management mechanism introduced in Linux 2.6. It is represented by struct kobject in the kernel. Through this data structure, all devices have a unified interface at the underlying layer. kobject provides basic object management, which is the core structure of the Linux 2.6 device model. It is closely associated with the sysfs file system, each kobject object registered in the kernel corresponds to a directory in the sysfs file system.
The kobject structure is defined:
Struct kobject {
Char * k_name; pointer to device name
Char name [kobj_name_len]; device name
Struct kref; object reference count
Struct list_head entry; it is attached to the Unit in the kset
Struct kobject * parent; pointer to parent object
Struct kset * kset; pointer to the kset
Struct kobj_type * ktype; pointer to its object type descriptor
Struct dentry * dentry; file Node path pointer corresponding to this object in sysfs File System
};
The kref field indicates the reference count of the object. The kernel manages the reference count of the object through kref. The Kernel provides two functions, kobject_get () and kobject_put (), to increase and decrease the reference count respectively, when the reference count is 0, all resources used by this object will be released.
The ktype field is a pointer to the kobj_type structure, indicating the type of the object. The kobj_type data structure contains three fields: A release method is used to release resources occupied by kobject; A sysfs_ops Pointer Points to the sysfs operation table and a default attribute list of sysfs file systems. The sysfs operation table includes two functions: store () and show (). When the user State reads the attribute, the show () function is called. The Function Code specifies that the attribute value is stored in the buffer and returned to the user State. The store () function is used to store the attribute value passed in the user State.
Kset kernel object set
Kobject is usually organized into a hierarchical structure through kset. kset is a set of kobject of the same type. It is expressed in the kernel using the kset data structure and is defined:
Struct kset {
Struct subsystem * subsys; pointer to the subsystem
Struct kobj_type * ktype; pointer to the kset object type descriptor
Struct list_head list; used to connect the linked list headers of all kobject in the kset
Struct kobject kobj; embedded kobject
Struct kset_hotplug_ops * hotplug_ops; pointer to hot swapping operation table
};
All the kobject contained in the kset is organized into a bidirectional cyclic linked list. The list field is the header of the linked list. The ktype field points to a kobj_type structure, which is shared by all the kobject in the kset, indicating the type of these objects. The kset data structure is also embedded with a kobject object (represented by the kobj domain). The parent fields of all the kobject objects belonging to this kset point to this embedded object. In addition, kset depends on kobj to maintain reference count: kset reference count is actually the reference count of the embedded kobject object.
Subsystem Kernel Object Subsystem
The subsystem is a collection of ksets that describe a type of device subsystems in the system. For example, block_subsys indicates all Block devices, corresponding to the block directory in the sysfs file system. Similarly, devices_subsys corresponds to the devices directory in sysfs and describes all devices in the system. The subsystem is described by the struct subsystem data structure and is defined:
Struct subsystem {
Struct kset; embedded kset object
Struct rw_semaphore rwsem; mutex access semaphore
};
Each kset must belong to a subsystem. You can add a kset to the subsystem by setting the subsys domain in the kset structure to point to the specified subsystem. All ksets attached to the same subsystem share the same rwsem semaphore, which is used to synchronously access the linked list in the kset.
Basic Structure of Linux unified Device Model
| Type |
Content |
Corresponding kernel data structure |
Corresponding to/sys items |
| Device (devices) |
The device is the most basic type in this model, and is organized in layers by the connection of the device. |
struct device |
/sys/devices/*/*/.../ |
| Device Drivers) |
Install multiple identical devices in one system. Only one driver is required. |
struct device_driver |
/sys/bus/pci/drivers/*/ |
| Bus Type (bus types) |
Manage all devices connected to this bus at the entire bus level |
struct bus_type |
/sys/bus/*/ |
| Device classes) |
This is a device Hierarchy Tree organized by function. For example, the USB interface and the PS/2 interface are input devices, which will appear under/sys/class/input /. |
struct class |
/sys/class/*/ |
The definition of struct device in <Linux/device. h> is as follows:
Struct device {
Struct klist klist_children;
Struct klist_node knode_parent;/* node in sibling list */
Struct klist_node knode_driver;
Struct klist_node knode_bus;
Struct device * parent;
Struct kobject kobj;
Char bus_id [bus_id_size];/* position on parent bus */
Struct device_type * type;
Unsigned is_registered: 1;
Unsigned uevent_suppress: 1;
Struct semaphore SEM;/* semaphore to synchronize callto
* Its driver.
*/
Struct bus_type * bus;/* type of bus device is on */
Struct device_driver * driver;/* Which driver has allocated this
Device */
Void * driver_data;/* data private to the driver */
Void * platform_data;/* platform specific data, Device
Core doesn' t touch it */
Struct dev_pm_info power;
# Ifdef config_numa
Int numa_node;/* NUMA node this device is close */
# Endif
U64 * dma_mask;/* DMA mask (if DMA 'able device )*/
U64 * dma_mask;/* DMA mask (if DMA 'able device )*/
U64 coherent_dma_mask;/* Like dma_mask, but
Alloc_coherent mappings
Not all hardware supports
64-bit addresses for consistent
Allocations such descriptors .*/
Struct device_dma_parameters * dma_parms;
Struct list_head dma_pools;/* DMA pools (if DMA 'ble )*/
Struct dma_coherent_mem * dma_mem;/* internal for coherent mem
Override */
/* Arch specific additions */
Struct dev_archdata archdata;
Spinlock_t devres_lock;
Struct list_head devres_head;
/* Class_device migration path */
Struct list_head node;
Struct class * class;
Dev_t devt;/* dev_t, creates the sysfs "Dev "*/
Struct attribute_group ** groups;/* optional groups */
Void (* release) (struct device * Dev );
};
Among them, the most important ones are:
Struct device * parent;
Struct kobject kobj;
Struct bus_type * bus;
Struct device_driver * driver;
Struct class * class;
Dev_t devt;
For some fields, the above struct definition has an explanation.
<Linux/device. h>
Struct device_driver {
Const char * Name;
Struct bus_type * bus;
Struct module * owner;
Const char * mod_name;/* used for built-in modules */
INT (* probe) (struct device * Dev );
INT (* remove) (struct device * Dev );
Void (* shutdown) (struct device * Dev );
INT (* suspend) (struct device * Dev, pm_message_t State );
INT (* resume) (struct device * Dev );
Struct attribute_group ** groups;
Struct driver_private * P;
};
The definition of device_driver is short, including names such as name and bus, and the five actions probe, remove, shutdown, suspend, and resume.
<Linux/device. h>
Struct bus_type {
Const char * Name;
Struct bus_attribute * bus_attrs;
Struct device_attribute * dev_attrs;
Struct driver_attribute * drv_attrs;
INT (* match) (struct device * Dev, struct device_driver * DRV );
INT (* uevent) (struct device * Dev, struct kobj_uevent_env * env );
INT (* probe) (struct device * Dev );
INT (* remove) (struct device * Dev );
Void (* shutdown) (struct device * Dev );
INT (* suspend) (struct device * Dev, pm_message_t State );
INT (* suspend_late) (struct device * Dev, pm_message_t State );
INT (* resume_early) (struct device * Dev );
INT (* resume) (struct device * Dev );
Struct bus_type_private * P;
};
Struct class {
Const char * Name;
Struct module * owner;
Struct kset subsys;
Struct list_head children;
Struct list_head devices;
Struct list_head interfaces;
Struct kset class_dirs;
Struct semaphore SEM;/* locks children, devices, interfaces */
Struct class_attribute * class_attrs;
Struct class_device_attribute * class_dev_attrs;
Struct device_attribute * dev_attrs;
INT (* uevent) (struct class_device * Dev, struct kobj_uevent_env * env );
INT (* dev_uevent) (struct device * Dev, struct kobj_uevent_env * env );
Void (* release) (struct class_device * Dev );
Void (* class_release) (struct class * class );
Void (* dev_release) (struct device * Dev );
INT (* suspend) (struct device * Dev, pm_message_t State );
INT (* resume) (struct device * Dev );
};
Struct class defines the criteria for classification by function, but this standard is actually reflected in the structure of/sys/class/through struct class_device:
Struct class_device {
Struct list_head node;
Struct kobject kobj;
Struct class * class;
Dev_t devt;
Struct device * dev;
Void * class_data;
Struct class_device * parent;
Struct attribute_group ** groups;
Void (* release) (struct class_device * Dev );
INT (* uevent) (struct class_device * Dev, struct kobj_uevent_env * env );
Char class_id [bus_id_size];
};
Sys File System
Sysfs is a by-product in the development of the Linux unified device model. sysfs is a ram-based filesystem initially based on ramfs. it provides a means to export kernel data structures, their attributes, and the linkages between them to userspace
Sys File System directory:
SYS: Block, bus, devices, firmware, FS, kernel, module, power, etc.
These directories demonstrate the kernel's model and method for unified management of various devices.
/Sys/devices
This is a hierarchical Expression Model of the kernel for all devices in the system and the most important directory structure for managing devices in the/sys file system.
/Sys/dev
This directory maintains a symbolic link file that links the primary and secondary numbers (Major: minor) of the device by character to the real device (/sys/devices.
/Sys/Bus
The directory structure of the kernel device is layered by bus type. All devices in devices are connected to a certain bus. The Symbolic Links of each specific device can be found under each specific bus.
/Sys/class
This is a device model categorized by device features. For example, all input devices in the system appear under/sys/class/input, regardless of the bus they connect to the system.
/Sys/blockDeprecated
/Sys/firmware
User space interface of the system's firmware Loading Mechanism
/Sys/fs
This is designed to describe all file systems in the system, including the file system itself and the mounted storage points classified by file system, but currently only fuse, A few file systems such as gfs2 support sysfs interfaces. Some traditional Virtual File System (VFS) hierarchical control parameters are still in the sysctl (/proc/sys/Fs) interface;
/Sys/kernel
Here is the location of all the adjustable parameters in the kernel. Currently, only uevent_helper, kexec_loaded, mm, and the New Slab allocator are used, other kernel adjustable parameters are still in the sysctl (/proc/sys/kernel) interface;
/Sys/Module
Information about all modules in the system, whether these modules are compiled into the kernel image file (vmlinuz) in the inlined mode or as an external module (Ko file ), may all appear in/sys/module:
* After being compiled into an external module (Ko file), the corresponding/sys/module/<module_name> /, in addition, some attribute files and attribute directories will appear in this directory to indicate information about the modules, such as the version number, loading status, and provided drivers;
* For a module compiled as an inline mode, the corresponding/sys/module/<module_name> appears only when it has a module parameter with a non-0 attribute, the available parameters of these modules are displayed in/sys/modules/<modname>/parameters/<param_name>,
O For example, The read/write parameter/sys/module/printk/parameters/time controls whether the inline module printk adds a time prefix when printing kernel messages;
O parameters of all inline modules can also be set by "<module_name>. <param_name >=< value> "is written in the kernel startup parameters. For example, add the parameter" printk. time = 1 "is the same as writing 1 to"/sys/module/printk/parameters/Time;
* Inline modules without non-zero attribute parameters do not appear here.
/Sys/power
Here is the power option in the system. There are several attribute files in this directory that can be used to control the power status of the entire machine. For example, you can write control commands to shut down or restart the machine.
References:
[1] Chen Lijun Linux Device Driver Model Part 1, Part 2, part 3, Part 4
[2] Cheng Ren uses the Sys File System to access the Linux kernel full text
[3] http://blog.chinaunix.net/u2/86638/showart_1850276.html