Dans le modèle de périphérique, le bus, le périphérique, le pilote de périphérique, etc. sont relativement faciles à comprendre, car ils correspondent tous à des choses réelles et toute la logique est centrée autour de ces entités. Cependant, la classe décrite dans cet article est quelque peu différente, car elle est virtuelle, juste pour faire abstraction des points communs de l'appareil.
Par exemple, si des personnes du même âge et ayant besoin d'acquérir des connaissances similaires se réunissent pour étudier, elles forment une classe. Cette classe peut avoir son propre nom (comme « 295 »), mais elle n'a aucun sens sans les étudiants (Devices) qui la composent. De plus, quelle est la plus grande signification de l’existence des classes ? Chaque cours est dispensé par un professeur ! Comme l’enseignant n’a besoin de parler qu’une seule fois, tous les élèves d’une classe peuvent l’entendre. Si chaque élève étudie à la maison, un enseignant sera embauché pour chaque élève pour leur enseigner de cette façon. La plupart du contenu est le même, ce qui constitue un énorme gaspillage.
La classe dans le modèle d'appareil offre des fonctionnalités similaires. Par exemple, certains appareils similaires (étudiants) doivent fournir des interfaces (cours) similaires avec l'espace utilisateur. Si chaque pilote de périphérique doit être implémenté une seule fois, cela entraînera une grande quantité de code redondant dans le noyau, ce qui constitue un énorme gaspillage. Ainsi, Class a dit : "Laissez-moi vous aider à le mettre en œuvre, à condition que vous sachiez comment l'utiliser."
C'est la fonction de Class dans le modèle de l'appareil. Combiné avec les commentaires du noyau : une classe est une vue de niveau supérieur d'un périphérique qui résume les détails d'implémentation de bas niveau (include/linux/device.h line326), elle est facile à comprendre.
struct class est l'abstraction de classe, sa définition est la suivante :
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: };
«
En fait, la classe struct et le bus struct sont très similaires, expliqués comme suit :
name, le nom de la classe, sera reflété dans le répertoire "/sys/class/".
class_atrrs, l'attribut par défaut de cette classe, créera automatiquement le fichier d'attribut correspondant sous "/sys/class/xxx_class" lorsque la classe est enregistrée dans le noyau.
dev_attrs, les attributs de chaque périphérique de cette classe, créeront automatiquement le fichier d'attributs correspondant dans le répertoire sysfs du périphérique lorsque celui-ci est enregistré dans le noyau.
dev_bin_attrs, similaire à dev_attrs, n'est qu'un attribut de type binaire.
dev_kobj, indique le répertoire sous /sys/dev/ pour les appareils de cette classe. Actuellement, il existe généralement deux types : char et block Si dev_kobj est NULL, char est sélectionné par défaut.
dev_uevent, lorsqu'un appareil de cette classe change, la fonction de rappel uevent de la classe sera appelée.
class_release, la fonction de rappel utilisée pour la version elle-même.
dev_release, utilisé comme fonction de rappel pour les appareils de la classe release. Dans l'interface device_release, le périphérique, le type de périphérique et la classe où se trouve le périphérique seront vérifiés afin de voir si l'interface de version est enregistrée. Si tel est le cas, l'interface de version correspondante sera appelée pour libérer le pointeur de périphérique.
p, c'est la même chose que la structure du bus struct dans "Linux Device Model (6)_Bus" et ne sera pas expliquée à nouveau.
”
struct class_interface est une structure qui permet au pilote de classe d'appeler des fonctions de rappel prédéfinies (add_dev et remove_dev) lorsqu'un périphérique est ajouté ou supprimé dans la classe. Alors, que fais-tu en les appelant ? Vous pouvez faire ce que vous voulez (comme changer le nom du périphérique), et cela est implémenté par le pilote de classe spécifique.
La structure est définie comme suit :
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的注册类似,主要包括:
- Allouez de l'espace pour le pointeur de type struct subsys_private (cp) dans la structure de classe et initialisez les champs qu'il contient, notamment cp->subsys.kobj.kset, cp->subsys.kobj.ktype, etc.
- Appelez kset_register pour enregistrer la classe (rappelez-vous la description dans "Linux Device Model (6)_Bus", une classe est un sous-système, donc l'enregistrement d'une classe est également un sous-système d'enregistrement). Une fois le processus terminé, un répertoire correspondant à la classe (sous-système) sera créé dans le répertoire /sys/class/
- Appelez l'interface add_class_attrs pour ajouter l'attribut pointé par le pointeur class_attrs dans la structure de classe au noyau. Après exécution, vous verrez les fichiers correspondant à ces attributs dans le répertoire /sys/class/xxx_class/
”
Dans "Modèle de périphérique Linux (5)_device et pilote de périphérique", nous avons parlé des deux structures de données struct device et struct device_driver La structure du périphérique struct contiendra un pointeur de classe struct (cela montre de côté que la classe est le périphérique A. (la collection, même la classe peut être le pilote du périphérique). Lorsqu'un pilote de classe enregistre une classe auprès du noyau, il doit utiliser le périphérique de la classe en pointant son propre pointeur de classe vers la classe. Le noyau gère le reste lors de l'enregistrement du périphérique.
Dans cette section, nous parlerons des actions liées au recours collectif lors de l'enregistrement de l'appareil :
«
L'enregistrement des appareils est finalement implémenté par l'interface device_add (drivers/base/core.c). Les actions liées aux classes dans cette interface incluent :
.
- Appeler l'interface device_add_class_symlinks pour créer différents liens symboliques décrits à la section 3.1, à savoir : dans le répertoire de la classe correspondante, créer un lien symbolique pointant vers le périphérique, dans le répertoire du périphérique, créer un lien symbolique nommé sous-système pointant vers le périphérique ; répertoire de classe correspondant
- Appelez device_add_attrs pour ajouter les attributs spécifiés par la classe (class->dev_attrs)
- S'il existe une fonction de rappel add_dev correspondant à la classe, appelez la fonction de rappel
”
En fait, après la fin de cet article, Wowo n'a toujours pas compris comment les classes sont utilisées dans le noyau. Mais cela n'a pas d'importance dans l'analyse ultérieure des sous-systèmes (tels que le sous-système d'entrée, le sous-système RTC, etc.), nous verrons de nombreux cas d'utilisation des classes. Le moment venu, cela deviendra très clair lorsque nous regarderons en arrière et résumerons.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!