In the device model, Bus, Device, Device driver, etc. are relatively easy to understand, because they all correspond to real things, and all logic is centered around these entities. However, the Class to be described in this article is somewhat different, because it is virtual, just to abstract the commonality of the device.
For example, if some people of similar age and need to acquire similar knowledge gather together to study, they form a class. This class can have its own name (such as "295"), but it has no meaning without the students (Devices) that make up it. In addition, what is the greatest significance of the existence of classes? Every course is taught by a teacher! Because the teacher only needs to speak once, all students in a class can hear it. If every student is studying at home, a teacher will be hired for each student to teach them this way. Most of the content is the same, which is a huge waste.
Class in the device model provides similar functions. For example, some similar Devices (students) need to provide similar interfaces (courses) to user space. If each device driver has to be implemented once, it will lead to a large amount of redundant code in the kernel, which is a huge waste. Therefore, Class said: "Let me help you implement it, as long as you know how to use it."
This is the function of Class in the device model. Combined with the kernel's comments: A class is a higher-level view of a device that abstracts out low-level implementation details (include/linux/device.h line326), it is easy to understand.
struct class is the abstraction of class, its definition is as follows:
1: /* include/linux/device.h, line 332 */ 2: struct class { 3: const char *name; 4: struct module *owner; 5: 6: struct class_attribute *class_attrs; 7: struct device_attribute *dev_attrs; 8: struct bin_attribute *dev_bin_attrs; 9: struct kobject *dev_kobj; 10: 11: int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); 12: char *(*devnode)(struct device *dev, umode_t *mode); 13: 14: void (*class_release)(struct class *class); 15: void (*dev_release)(struct device *dev); 16: 17: int (*suspend)(struct device *dev, pm_message_t state); 18: int (*resume)(struct device *dev); 19: 20: const struct kobj_ns_type_operations *ns_type; 21: const void *(*namespace)(struct device *dev); 22: 23: const struct dev_pm_ops *pm; 24: 25: struct subsys_private *p; 26: };
“
In fact, struct class and struct bus are very similar, explained as follows:
name, the name of the class, will be reflected in the "/sys/class/" directory.
class_atrrs, the default attribute of the class, will automatically create the corresponding attribute file under "/sys/class/xxx_class" when the class is registered in the kernel.
dev_attrs, the attributes of each device under this class will automatically create the corresponding attribute file in the sysfs directory of the device when the device is registered to the kernel.
dev_bin_attrs, similar to dev_attrs, is just a binary type attribute.
dev_kobj, indicates the directory under /sys/dev/ of the device under this class. Currently, there are generally two types: char and block. If dev_kobj is NULL, char is selected by default.
dev_uevent, when a device under this class changes, the class's uevent callback function will be called.
class_release, the callback function used for release itself.
dev_release, used as a callback function for devices within the release class. In the device_release interface, the Device, Device Type and the class where the Device is located will be checked in order to see whether the release interface is registered. If so, the corresponding release interface will be called to release the device pointer.
p, is the same as the struct bus structure in "Linux Device Model (6)_Bus" and will not be explained again.
”
struct class_interface is a structure that allows the class driver to call preset callback functions (add_dev and remove_dev) when a device is added or removed under the class. So what do you do with calling them? You can do whatever you want (such as changing the name of the device), and it is implemented by the specific class driver.
The structure is defined as follows:
1: /* include/linux/device.h, line 434 */ 2: struct class_interface { 3: struct list_head node; 4: struct class *class; 5: 6: int (*add_dev) (struct device *, struct class_interface *); 7: void (*remove_dev) (struct device *, struct class_interface *); 8: };
看完上面的东西,蜗蜗依旧糊里糊涂的,class到底提供了什么功能?怎么使用呢?让我们先看一下现有Linux系统中有关class的状况(这里以input class为例):
“
root@android:/ # ls /sys/class/input/ -l
lrwxrwxrwx root root 2014-04-23 03:39 event0 -> ../../devices/platform/i2c-gpio.17/i2c-17/17-0066/max77693-muic/input/input0/event0
lrwxrwxrwx root root 2014-04-23 03:39 event1 -> ../../devices/platform/gpio-keys.0/input/input1/event1
lrwxrwxrwx root root 2014-04-23 03:39 event10 -> ../../devices/virtual/input/input10/event10
lrwxrwxrwx root root 2014-04-23 03:39 event2 -> ../../devices/platform/s3c2440-i2c.3/i2c-3/3-0048/input/input2/event2
…
lrwxrwxrwx root root 2014-04-23 03:39 event8 -> ../../devices/platform/soc-audio/sound/card0/input8/event8
lrwxrwxrwx root root 2014-04-23 03:39 event9 -> ../../devices/platform/i2c-gpio.8/i2c-8/8-0020/input/input9/event9
lrwxrwxrwx root root 2014-04-23 03:39 input0 -> ../../devices/platform/i2c-gpio.17/i2c-17/17-0066/max77693-muic/input/input0
…
lrwxrwxrwx root root 2014-04-23 03:39 mice -> ../../devices/virtual/input/miceroot@android:/ # ls /sys/devices/platform/s3c2440-i2c.3/i2c-3/3-0048/input/input2/event2/ -l
-r–r–r– root root 4096 2014-04-23 04:08 dev
lrwxrwxrwx root root 2014-04-23 04:08 device -> ../../input2
drwxr-xr-x root root 2014-04-23 04:08 power
lrwxrwxrwx root root 2014-04-23 04:08 subsystem -> ../../../../../../../../class/input
-rw-r–r– root root 4096 2014-04-23 04:08 ueventroot@android:/ # ls /sys/devices/virtual/input/mice/ -l
-r–r–r– root root 4096 2014-04-23 03:57 dev
drwxr-xr-x root root 2014-04-23 03:57 power
lrwxrwxrwx root root 2014-04-23 03:57 subsystem -> ../../../../class/input
-rw-r–r– root root 4096 2014-04-23 03:57 uevent”
看上面的例子,发现input class也没做什么实实在在的事儿,它(input class)的功能,仅仅是:
算了,我们还是先分析一下Class的核心逻辑都做了哪些事情,至于class到底有什么用处,可以在后续具体的子系统里面(如input子系统),更为细致的探讨。
“
class的注册,是由__class_register接口(它的实现位于”drivers/base/class.c, line 609″)实现的,它的处理逻辑和bus的注册类似,主要包括:
- Allocate space for the struct subsys_private type pointer (cp) in the class structure, and initialize the fields in it, including cp->subsys.kobj.kset, cp->subsys.kobj.ktype, etc.
- Call kset_register to register the class (recall the description in "Linux Device Model (6)_Bus", a class is a subsystem, so registering a class is also a registration subsystem). After the process is completed, a directory corresponding to the class (subsystem) will be created in the /sys/class/ directory
- Call the add_class_attrs interface to add the attribute pointed to by the class_attrs pointer in the class structure to the kernel. After execution, you will see the files corresponding to these attributes in the /sys/class/xxx_class/ directory
”
In "Linux Device Model (5)_device and device driver", we have talked about the two data structures struct device and struct device_driver. The struct device structure will contain a struct class pointer (this explains the class from the side) It is a collection of devices, and even class can be the driver of the device). When a class driver registers a class with the kernel, it needs to use the device of the class by pointing its own class pointer to the class. The kernel handles the rest when registering the device.
In this section, we will talk about the class-related actions when registering the device:
“
Device registration is ultimately implemented by the device_add interface (drivers/base/core.c). The class-related actions in this interface include:
- Call the device_add_class_symlinks interface to create various symbolic links described in Section 3.1, that is: in the directory of the corresponding class, create a symbolic link pointing to the device; in the directory of the device, create a symbolic link named subsystem pointing to the corresponding class directory
- Call device_add_attrs to add attributes specified by class (class->dev_attrs)
- If there is an add_dev callback function corresponding to the class, call the callback function
”
In fact, after the end of this article, Wowo still has not figured out how classes are used in the kernel. But it doesn’t matter. In the subsequent analysis of subsystems (such as input subsystem, RTC subsystem, etc.), we will see many use cases of classes. When the time comes, it will be very clear when we look back and summarize.
The above is the detailed content of Detailed explanation of Linux device model (7)_Class. For more information, please follow other related articles on the PHP Chinese website!