장치 모델에서 버스, 장치, 장치 드라이버 등은 모두 실제 사물에 해당하고 모든 논리가 이러한 엔터티를 중심으로 돌아가기 때문에 상대적으로 이해하기 쉽습니다. 다만, 본 글에서 설명하는 클래스는 가상 클래스이므로 장치의 공통성을 추상화하기 위해 다소 차이가 있다.
예를 들어, 비슷한 나이대에 비슷한 지식이 필요한 사람들이 모여서 공부한다면, 그들은 반을 형성합니다. 이 클래스는 고유한 이름(예: "295")을 가질 수 있지만 이를 구성하는 학생(장치)이 없으면 의미가 없습니다. 또한, 클래스의 존재의 가장 큰 의미는 무엇입니까? 모든 강좌는 선생님이 진행합니다! 교사는 한 번만 말하면 되기 때문에 수업에 참여하는 학생들은 그 내용을 들을 수 있습니다. 모든 학생이 집에서 공부한다면 각 학생마다 교사를 고용하여 이런 식으로 가르칠 것입니다. 대부분의 내용이 동일해서 엄청난 낭비입니다.
장치 모델의 클래스는 유사한 기능을 제공합니다. 예를 들어 일부 유사한 장치(학생)는 사용자 공간에 유사한 인터페이스(강의)를 제공해야 합니다. 각 장치 드라이버를 한 번만 구현해야 한다면 커널에 많은 양의 중복 코드가 발생하게 되어 엄청난 낭비가 됩니다. 그래서 Class는 "사용 방법을 알고 있는 한 구현을 도와드리겠습니다."라고 말했습니다.
기기 모델의 클래스 기능입니다. 커널 설명과 결합하면 클래스는 낮은 수준의 구현 세부 정보(include/linux/device.h line326)를 추상화하는 장치의 상위 수준 보기이므로 이해하기 쉽습니다.
struct 클래스는 클래스의 추상화이며 정의는 다음과 같습니다.
으아아아“
사실 구조체 클래스와 구조체 버스는 매우 유사하며 다음과 같이 설명됩니다.
name, 클래스 이름은 "/sys/class/" 디렉터리에 반영됩니다.
이 클래스의 기본 속성인 class_atrrs는 클래스가 커널에 등록되면 "/sys/class/xxx_class" 아래에 해당 속성 파일을 자동으로 생성합니다.
dev_attrs, 이 클래스에 속한 각 장치의 속성은 장치가 커널에 등록될 때 장치의 sysfs 디렉터리에 해당 속성 파일을 자동으로 생성합니다.
dev_bin_attrs는 dev_attrs와 유사하며 바이너리 유형 속성일 뿐입니다.
dev_kobj는 이 클래스 아래의 장치가 /sys/dev/ 아래의 디렉터리에 있음을 의미합니다. 현재 일반적으로 char 및 block의 두 가지 유형이 있습니다. dev_kobj가 NULL이면 기본적으로 char가 선택됩니다.
dev_uevent, 이 클래스 아래의 장치가 변경되면 해당 클래스의 uevent 콜백 함수가 호출됩니다.
class_release, 릴리스 자체에 사용되는 콜백 함수입니다.
dev_release, 릴리스 클래스 내의 장치에 대한 콜백 함수로 사용됩니다. device_release 인터페이스에서는 릴리스 인터페이스가 등록되어 있는지 확인하기 위해 Device, Device Type 및 Device가 위치한 클래스를 검사합니다. 등록된 경우 해당 릴리스 인터페이스를 호출하여 장치 포인터를 해제합니다.
p, "Linux Device Model (6)_Bus"의 버스 구조체 구조와 동일하므로 다시 설명하지 않겠습니다.
”
struct class_interface는 클래스 아래에 장치가 추가되거나 제거될 때 클래스 드라이버가 미리 설정된 콜백 함수(add_dev 및 제거_dev)를 호출할 수 있도록 하는 구조입니다. 그럼 그들에게 전화해서 무엇을 합니까? 원하는 것은 무엇이든(예: 장치 이름 변경) 수행할 수 있으며 이는 특정 클래스 드라이버에 의해 구현됩니다.
구조는 다음과 같이 정의됩니다:
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的注册类似,主要包括:
- 클래스 구조에서 struct subsys_private 유형 포인터(cp)에 공간을 할당하고 cp->subsys.kobj.kset, cp->subsys.kobj.ktype 등을 포함하여 그 안의 필드를 초기화합니다.
- kset_register를 호출하여 클래스를 등록합니다("Linux Device Model (6)_Bus"의 설명을 기억하세요. 클래스는 하위 시스템이므로 클래스 등록도 등록 하위 시스템입니다). 프로세스가 완료되면 /sys/class/ 디렉터리에 클래스(서브시스템)에 해당하는 디렉터리가 생성됩니다
- add_class_attrs 인터페이스를 호출하여 클래스 구조의 class_attrs 포인터가 가리키는 속성을 커널에 추가합니다. 실행 후에는 /sys/class/xxx_class/ 디렉터리
에서 이러한 속성에 해당하는 파일을 볼 수 있습니다.”
"Linux 장치 모델(5)_device 및 장치 드라이버"에서 우리는 struct device와 struct device_driver라는 두 가지 데이터 구조에 대해 이야기했습니다. struct 장치 구조에는 구조체 클래스 포인터가 포함됩니다(이것은 클래스가 장치 A라는 측면에서 보여줍니다). 심지어 클래스의 컬렉션은 장치의 드라이버가 될 수도 있습니다). 클래스 드라이버가 커널에 클래스를 등록할 때 클래스에 대한 자체 클래스 포인터를 가리켜 클래스의 장치를 사용해야 합니다. 커널은 장치를 등록할 때 나머지를 처리합니다.
이 섹션에서는 장치 등록 시 수업 관련 작업에 대해 설명합니다.
“
장치 등록은 궁극적으로 device_add 인터페이스(drivers/base/core.c)에 의해 구현됩니다. 이 인터페이스의 클래스 관련 작업은 다음과 같습니다.
- device_add_class_symlinks 인터페이스를 호출하여 섹션 3.1에 설명된 다양한 심볼릭 링크를 생성합니다. 즉, 해당 클래스의 디렉터리에서 장치를 가리키는 심볼릭 링크를 생성하고, 해당 클래스를 가리키는 subsystem이라는 심볼릭 링크를 생성합니다. 해당 수업 디렉토리
- 클래스에 지정된 속성을 추가하려면 device_add_attrs를 호출하세요(class->dev_attrs)
- 해당 클래스에 해당하는 add_dev 콜백 함수가 있으면 콜백 함수를 호출하세요
”
사실 이 글이 끝난 후에도 Wowo는 커널에서 클래스가 어떻게 사용되는지 아직 파악하지 못했습니다. 그러나 이는 중요하지 않습니다. 하위 시스템(예: 입력 하위 시스템, RTC 하위 시스템 등)에 대한 후속 분석에서는 클래스의 많은 사용 사례를 볼 수 있습니다. 때가 되면 우리가 되돌아보고 요약하면 매우 분명해질 것입니다.
위 내용은 Linux 장치 모델에 대한 자세한 설명(7)_클래스의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!