Device driver model of linux kernel
Preface
At the end of the day, LDD3 was basically finished (in a big way). There is still a part of the device driver here. Drink a cup of medlar tea, pat my slightly lazy face, and record this part.
This blog is going to write a few parts
- kobject subsystem, the cornerstone of equipment model
- General framework of device model bus, device and driver model
- About the driving virtual memory file system - Sysfs system
ok,let's begin...
1, kobject subsystem, the cornerstone of equipment model
In the large Object-oriented framework or software system, in order to reuse the code, most systems will create an Object object, which is the ancestor of other objects. As the pioneering leader, it generally makes the highest abstraction for the objects needed in the software system. For its descendants, most of them need to inherit Object, so as to play the role of inheritance and polymorphism in Object-oriented.
linux developed in C language is more or less used in the device driver module.
Kobject is the basic structure of the device model, while many platforms, buses or frameworks in the kernel are based on kobject (for example, the bus, device and driver models mentioned later). Because linux is completed in C language, the pure inheritance relationship of object-oriented can't be embodied, so the way of descendants of kobject "inheriting" this ancestor is to include an object structure. For example, the character device cdev in the device driver has the following members.
struct cdev { struct kobject kobj; //Embedded kernel object struct module *owner; //The object pointer of the kernel module where the character device is located const struct file_operations *ops; //This structure describes the implementation method of character device and is a key structure struct list_head list; //Used to link all character devices registered with the kernel dev_t dev; //The equipment number of character equipment consists of main equipment number and secondary equipment number unsigned int count; //The number of secondary equipment numbers belonging to the same primary equipment number
Let's talk a little more briefly here. Some C + + textbooks call this "inheritance" method the combination method. At the same time, with this embedded combination, linux uses a method called container of() to realize polymorphism (use structure members to find structure). If you are interested, you can ask duniang.
Let's go back to kobject. In the 2.6 kernel, its basic structure is:
struct kobject { const char *name; struct list_head entry; struct kobject *parent; struct kset *kset; struct kobj_type *ktype; struct sysfs_dirent *sd; struct kref kref; unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; unsigned int uevent_suppress:1; };
In LDD3, Kobject has the following functions:
(1) , the reference count of the object. kref in the structure mainly realizes this function. It controls the life cycle of the object, that is, when there is no code holding the reference of the object in the kernel, the object can be deleted.
(2) Data structure. Object links a large number of data structures into a hierarchical architecture. (similar to the parent family tree of the object's subclass)
(3) , sysfs. Every object displayed in sysfs corresponds to this kobject, which is used for kernel interaction.
(4) , hot plug event processing. When the hardware in the system is hot swapped, under the control of the kobject subsystem, an event will be generated to inform the user space. (not covered in this article)
Several structures extended by kobject include kset, kobj_type and so on. Their functions are similar to those of object (or they cooperate with kobject to form the functions described above). There are many blogs on the Internet that say it's very good. At present, I can't think of any good innovations. I won't go over them here. Recommend a blog.
2, General framework of device model bus, device and driver model
There should be many frameworks in linux driver, but the most important one is the bus, device and driver model framework.
Come on, let's get a picture first.
In order to deal with the increasingly complex hardware devices, the original linux kernel is a bit unbearable. With the joint efforts of the hot-blooded youth who love linux all over the world, the bus and device driver model shown in the figure above should appear after version 2.6.
In this model, there are three concepts:
(1) , Bus. The Bus mentioned here is not the real hardware Bus inside the CPU, but a virtual concept. (I think it's called Bus because the device and driver can "hang" on it). To some extent, it's the controller of this model and the overall situation of the whole situation. Devices and drivers in the model need to be hung under it to be used. In the linux kernel, Bus type is used to describe a Bus.
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 (*resume)(struct device *dev); const struct dev_pm_ops *pm; struct bus_type_private *p; };
(2) Device. In the linux kernel, the device structure is used to describe. As shown below.
struct device { struct device *parent; struct device_private *p; struct kobject kobj; const char *init_name; /* initial name of the device */ struct device_type *type; struct mutex mutex; /* mutex to synchronize calls to * its driver. */ struct bus_type *bus; /* type of bus device is on */ struct device_driver *driver; /* which driver has allocated this device */ 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 to */ #endif u64 *dma_mask; /* dma mask (if dma'able device) */ u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as 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; #ifdef CONFIG_OF struct device_node *of_node; #endif dev_t devt; /* dev_t, creates the sysfs "dev" */ spinlock_t devres_lock; struct list_head devres_head; struct klist_node knode_class; struct class *class; const struct attribute_group **groups; /* optional groups */ void (*release)(struct device *dev); };
(3) Driver. In the linux kernel, the device driver is used to describe. As shown below.
struct device_driver { const char *name; struct bus_type *bus; struct module *owner; const char *mod_name; /* used for built-in modules */ bool suppress_bind_attrs; /* disables bind/unbind via sysfs */ #if defined(CONFIG_OF) const struct of_device_id *of_match_table; #endif 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); const struct attribute_group **groups; const struct dev_pm_ops *pm; struct driver_private *p; };
The linux kernel divides the device drivers into one managed device and one managed driver. When they are used, they need to be "hung" on the corresponding bus (kset in bus type, bus type in device and device driver). They are like a couple of little lovers, and bus is equivalent to matchmaker. When a device comes to the bus registration of the matchmaker, the bus matchmaker will traverse the registered device driver to find one that can match the device (using the match function in the bus type). The same is true when the device driver registers. It should be noted that generally speaking, a device can only match one driver, and a driver can match multiple devices. (in that case, the little couple here should be the little couple in ancient times, hehe)
Here I just talk about some big aspects, specific details. There are a lot of blogs and materials that are already very good. Here are some information.
1. Understanding Linux series from the perspective of requirements: bus, device and driver
2. Software architecture in Linux device driver
3, linux device driver model
4. How to call the probe function in linux driver
Let's talk more about it here. The bus, device and device driver architectures are also relatively low-level architectures. The more mature buses in the linux kernel are encapsulated on the underlying architectures (member variables and corresponding operation methods). Such as bus, pci bus and platform bus. If you want to know more about this model, you can simulate and write your own bus, create your own devices and drivers. Here are some information for you.
1. Write a platform bus from scratch
2. Character drive migration – bus, device, driver
3. Bus device driver model
3, About the driving virtual memory file system - Sysfs system
In linux system, in addition to some real file systems (such as ext2, ext3, etc.) stored on the media, there is also a file system called virtual memory. This file system only exists in memory, and when the power is off, the file system disappears. Most of the functions of this file system are to export the information of the kernel, so that kernel space and user space can interact. Such as proc, tmpfs, sysfs, etc.
For sysfs file system, its main function is to manage unified devices and drivers. So this file system is mostly related to drivers.
Uh huh. Yes, there are some other knowledge points in this part, such as class and udev. I haven't done them thoroughly yet. Let's start with these.