Im Gerätemodell sind Bus, Gerät, Gerätetreiber usw. relativ einfach zu verstehen, da sie alle realen Dingen entsprechen und sich die gesamte Logik um diese Entitäten dreht. Die in diesem Artikel beschriebene Klasse ist jedoch etwas anders, da sie virtuell ist, nur um die Gemeinsamkeit des Geräts zu abstrahieren.
Wenn sich beispielsweise Menschen gleichen Alters, die sich ähnliche Kenntnisse aneignen müssen, zum Lernen zusammenschließen, bilden sie eine Klasse. Diese Klasse kann einen eigenen Namen haben (z. B. „295“), hat aber ohne die Schüler (Geräte), aus denen sie besteht, keine Bedeutung. Was ist außerdem die größte Bedeutung der Existenz von Klassen? Jeder Kurs wird von einem Lehrer unterrichtet! Da der Lehrer nur einmal sprechen muss, können die Schüler einer Klasse es hören. Wenn jeder Schüler zu Hause lernt, wird für jeden Schüler ein Lehrer eingestellt, der ihn auf diese Weise unterrichtet. Die meisten Inhalte sind gleich, was eine große Verschwendung darstellt.
Klasse im Gerätemodell bietet ähnliche Funktionalität. Beispielsweise müssen einige ähnliche Geräte (Studenten) ähnliche Schnittstellen (Kurse) zum Benutzerbereich bereitstellen. Wenn jeder Gerätetreiber einmal implementiert werden muss, führt dies zu einer großen Menge an redundantem Code im Kernel, was eine enorme Verschwendung darstellt. Also sagte Class: „Lass mich dir bei der Umsetzung helfen, solange du weißt, wie man es benutzt.“
Dies ist die Funktion der Klasse im Gerätemodell. In Kombination mit den Kommentaren des Kernels: Eine Klasse ist eine Ansicht eines Geräts auf höherer Ebene, die Implementierungsdetails auf niedriger Ebene abstrahiert (include/linux/device.h Zeile 326). Dies ist leicht zu verstehen.
Strukturklasse ist die Abstraktion einer Klasse, ihre Definition lautet wie folgt:
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: };
“
Tatsächlich sind Strukturklasse und Strukturbus sehr ähnlich, was wie folgt erklärt wird:
Name, der Name der Klasse, wird im Verzeichnis „/sys/class/“ angezeigt.
class_atrrs, das Standardattribut dieser Klasse, erstellt automatisch die entsprechende Attributdatei unter „/sys/class/xxx_class“, wenn die Klasse im Kernel registriert wird.
dev_attrs, die Attribute jedes Geräts unter dieser Klasse, erstellen automatisch die entsprechende Attributdatei im sysfs-Verzeichnis des Geräts, wenn das Gerät beim Kernel registriert wird.
dev_bin_attrs ist, ähnlich wie dev_attrs, nur ein binäres Attribut.
dev_kobj gibt das Verzeichnis unter /sys/dev/ für Geräte dieser Klasse an. Derzeit gibt es im Allgemeinen zwei Typen: char und block. Wenn dev_kobj NULL ist, ist char standardmäßig ausgewählt.
dev_uevent: Wenn sich ein Gerät unter dieser Klasse ändert, wird die uevent-Rückruffunktion der Klasse aufgerufen.
class_release, die Rückruffunktion, die für die Veröffentlichung selbst verwendet wird.
dev_release, wird als Rückruffunktion für Geräte innerhalb der Release-Klasse verwendet. In der Schnittstelle „device_release“ werden das Gerät, der Gerätetyp und die Klasse, in der sich das Gerät befindet, überprüft, um festzustellen, ob die Freigabeschnittstelle registriert ist. Wenn ja, wird die entsprechende Freigabeschnittstelle aufgerufen, um den Gerätezeiger freizugeben.
p, es ist dasselbe wie die Strukturbusstruktur in „Linux Device Model (6)_Bus“ und wird nicht noch einmal erläutert.
“
struct class_interface ist eine Struktur, die es dem Klassentreiber ermöglicht, voreingestellte Rückruffunktionen (add_dev und remove_dev) aufzurufen, wenn ein Gerät unter der Klasse hinzugefügt oder entfernt wird. Was machst du also, wenn du sie anrufst? Sie können tun, was Sie wollen (z. B. den Namen des Geräts ändern), und dies wird vom jeweiligen Klassentreiber implementiert.
Die Struktur ist wie folgt definiert:
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的注册类似,主要包括:
- Weisen Sie Platz für den Typzeiger struct subsys_private (cp) in der Klassenstruktur zu und initialisieren Sie die darin enthaltenen Felder, einschließlich cp->subsys.kobj.kset, cp->subsys.kobj.ktype usw.
- Rufen Sie kset_register auf, um die Klasse zu registrieren (denken Sie an die Beschreibung in „Linux Device Model (6)_Bus“, eine Klasse ist ein Subsystem, daher ist die Registrierung einer Klasse auch ein Registrierungssubsystem). Nach Abschluss des Vorgangs wird im Verzeichnis /sys/class/ ein der Klasse (Subsystem) entsprechendes Verzeichnis erstellt
- Rufen Sie die Schnittstelle add_class_attrs auf, um das Attribut, auf das der Zeiger class_attrs in der Klassenstruktur zeigt, zum Kernel hinzuzufügen. Nach der Ausführung sehen Sie die diesen Attributen entsprechenden Dateien im Verzeichnis /sys/class/xxx_class/
“
In „Linux-Gerätemodell (5)_Gerät und Gerätetreiber“ haben wir über die beiden Datenstrukturen struct device und struct device_driver gesprochen. Die Struktur-Gerätestruktur enthält einen Strukturklassenzeiger (dies zeigt von der Seite, dass es sich bei der Klasse um Gerät A handelt). (Sammlung, sogar die Klasse kann der Treiber des Geräts sein). Wenn ein Klassentreiber eine Klasse beim Kernel registriert, muss er das Gerät der Klasse verwenden, indem er seinen eigenen Klassenzeiger auf die Klasse zeigt. Den Rest erledigt der Kernel bei der Registrierung des Geräts.
In diesem Abschnitt werden wir über die klassenbezogenen Aktionen bei der Registrierung des Geräts sprechen:
“
Die Geräteregistrierung wird letztendlich durch die Schnittstelle „device_add“ (drivers/base/core.c) implementiert. Zu den klassenbezogenen Aktionen in dieser Schnittstelle gehören:
- Rufen Sie die Schnittstelle device_add_class_symlinks auf, um verschiedene in Abschnitt 3.1 beschriebene symbolische Links zu erstellen, d entsprechendes Klassenverzeichnis
- Rufen Sie device_add_attrs auf, um durch die Klasse (class->dev_attrs) angegebene Attribute hinzuzufügen
- Wenn es eine add_dev-Rückruffunktion gibt, die der Klasse entspricht, rufen Sie die Rückruffunktion auf
“
Tatsächlich hat Wowo nach dem Ende dieses Artikels immer noch nicht herausgefunden, wie Klassen im Kernel verwendet werden. Aber das spielt keine Rolle. Bei der anschließenden Analyse von Subsystemen (wie Eingabesubsystem, RTC-Subsystem usw.) werden wir viele Anwendungsfälle von Klassen sehen. Wenn die Zeit gekommen ist, wird es sehr klar sein, wenn wir zurückblicken und zusammenfassen.
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Linux-Gerätemodells (7)_Klasse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!