ホームページ  >  記事  >  システムチュートリアル  >  Linuxデバイスモデルの詳細説明(7)_Class

Linuxデバイスモデルの詳細説明(7)_Class

WBOY
WBOY転載
2024-02-13 22:39:191222ブラウズ

######1。概要######

デバイス モデルでは、バス、デバイス、デバイス ドライバーなどはすべて実際のものに対応しており、すべてのロジックがこれらのエンティティを中心に配置されているため、比較的理解しやすいです。ただし、この記事で説明するクラスは、デバイスの共通性を抽象化するために仮想化されているため、多少異なります。

たとえば、同じような年齢で同じような知識を習得する必要がある人が集まって勉強する場合、クラスを形成します。このクラスには独自の名前 (「295」など) を付けることができますが、それを構成する生徒 (デバイス) がなければ意味がありません。また、授業の存在の最大の意義は何でしょうか?どのコースも講師が丁寧に指導します!教師が話す必要があるのは 1 回だけであるため、クラスの生徒全員がそれを聞くことができます。生徒全員が自宅で勉強している場合、この方法で生徒を指導するために生徒ごとに教師が雇われることになります。内容はほとんど同じなので、非常にもったいないです。

Linuxデバイスモデルの詳細説明(7)_Classデバイス モデルのクラスは同様の機能を提供します。たとえば、一部の同様のデバイス (学生) は、ユーザー空間に同様のインターフェイス (コース) を提供する必要があります。各デバイス ドライバーを 1 回実装する必要がある場合、カーネル内に大量の冗長コードが発生し、非常に無駄になります。したがって、クラスは「使用方法を知っている限り、実装を手伝いましょう。」と言いました。

これはデバイスモデルのクラスの機能です。カーネルのコメントと組み合わせると、クラスは低レベル実装の詳細 (include/linux/device.h line326) を抽象化したデバイスの高レベルのビューであり、理解しやすくなります。

2. データ構造の説明

2.1 構造体クラス

struct クラスはクラスの抽象化であり、その定義は次のとおりです:
リーリー #「

実際、構造体クラスと構造体バスは非常に似ており、次のように説明されます:

name (クラスの名前) は、「/sys/class/」ディレクトリに反映されます。 クラスのデフォルト属性である class_atrrs は、クラスがカーネルに登録されるときに、対応する属性ファイルを「/sys/class/xxx_class」の下に自動的に作成します。

dev_attrs、このクラスの各デバイスの属性は、デバイスがカーネルに登録されるときに、デバイスの sysfs ディレクトリに対応する属性ファイルを自動的に作成します。

dev_bin_attrs は、dev_attrs と同様、単なるバイナリ型の属性です。

dev_kobj は、このクラス配下のデバイスの /sys/dev/ 配下のディレクトリを示します。現在、一般的に char と block の 2 種類があり、dev_kobj が NULL の場合、デフォルトで char が選択されます。

dev_uevent、このクラスのデバイスが変更されると、クラスの uevent コールバック関数が呼び出されます。

class_release、リリース自体に使用されるコールバック関数。

dev_release。リリース クラス内のデバイスのコールバック関数として使用されます。 device_release インターフェイスでは、デバイス、デバイス タイプ、およびデバイスが配置されているクラスをチェックして、リリース インターフェイスが登録されているかどうかを確認し、登録されている場合は、対応するリリース インターフェイスを呼び出してデバイス ポインターを解放します。

p は、「Linux デバイス モデル (6)_Bus」の構造体バス構造と同じであるため、説明を省略します。

#2.2 構造体クラスインターフェイス

struct class_interface は、クラスの下でデバイスが追加または削除されたときに、クラス ドライバーが事前に設定されたコールバック関数 (add_dev および Remove_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: };

3. 功能及内部逻辑解析

3.1 class的功能

看完上面的东西,蜗蜗依旧糊里糊涂的,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/mice

root@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 uevent

root@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)的功能,仅仅是:

  • 在/sys/class/目录下,创建一个本class的目录(input)
  • 在本目录下,创建每一个属于该class的设备的符号链接(如,把“sys/devices/platform/s3c2440-i2c.3/i2c-3/3-0048/input/input2/event2”设备链接到”/sys/class/input/event2”),这样就可以在本class目录下,访问该设备的所有特性(即attribute)
  • 另外,device在sysfs的目录下,也会创建一个subsystem的符号链接,链接到本class的目录

算了,我们还是先分析一下Class的核心逻辑都做了哪些事情,至于class到底有什么用处,可以在后续具体的子系统里面(如input子系统),更为细致的探讨。

3.2 class的注册

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 デバイス モデル (6)_Bus」の説明を思い出してください。クラスはサブシステムであるため、クラスの登録も登録サブシステムです)。処理が完了すると、/sys/class/ディレクトリ
  • にクラス(サブシステム)に対応したディレクトリが作成されます。
  • add_class_attrs インターフェイスを呼び出して、クラス構造内の class_attrs ポインターが指す属性をカーネルに追加します。実行後、これらの属性に対応するファイルが /sys/class/xxx_class/ ディレクトリ
  • # に表示されます。

#''

3.3 デバイス登録時のクラス関連のアクション
「Linux デバイス モデル (5)_デバイスとデバイス ドライバー」では、struct device と struct device_driver という 2 つのデータ構造について説明しました。struct device 構造には、struct クラス ポインターが含まれます (クラスを側面から説明しています)。これはデバイスのコレクションであり、クラスさえもデバイスのドライバーになることができます)。クラス ドライバーがクラスをカーネルに登録するときは、独自のクラス ポインターをクラスにポイントして、そのクラスのデバイスを使用する必要があり、残りの部分はデバイスの登録時にカーネルが処理します。

このセクションでは、デバイスを登録するときのクラス関連のアクションについて説明します。

#「

デバイスの登録は、最終的に device_add インターフェイス (drivers/base/core.c) によって実装されます。このインターフェイスのクラス関連アクションには次のものが含まれます:

device_add_class_symlinks インターフェイスを呼び出して、セクション 3.1 で説明されているさまざまなシンボリック リンクを作成します。つまり、クラスに対応するディレクトリにデバイスを指すシンボリック リンクを作成し、デバイスのディレクトリにサブシステムを指すサブシステムという名前のシンボリック リンクを作成します。対応するクラスディレクトリ
  • device_add_attrs を呼び出して、クラスで指定された属性を追加します (class->dev_attrs)
  • クラスに対応する add_dev コールバック関数がある場合は、そのコールバック関数を呼び出します。
  • #''

4 結論

実際のところ、この記事を終えた後でも、Wowo はカーネル内でクラスがどのように使用されるかをまだ理解していません。その後のサブシステム (入力サブシステム、RTC サブシステムなど) の分析では、クラスの使用例が多数登場します。その時が来て、振り返って要約すると、非常に明確になります。

以上がLinuxデバイスモデルの詳細説明(7)_Classの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlxlinux.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。