ホームページ >システムチュートリアル >Linux >Linuxデバイスモデル(3)_Uevent

Linuxデバイスモデル(3)_Uevent

WBOY
WBOY転載
2024-02-11 13:06:171047ブラウズ

1.ueventの機能

Uevent は Kobject の一部であり、Kobject の状態が変化したとき (追加、削除など) にユーザー空間プログラムに通知するために使用されます。このようなイベントを受信すると、ユーザー空間プログラムはそれを適切に処理します。

通常、このメカニズムはホットプラグ対応デバイスをサポートするために使用されます。たとえば、USB フラッシュ ドライブが挿入されると、USB 関連ドライバーは、USB フラッシュ ドライブを表すために使用されるデバイス構造 (対応する kobject を含む) を動的に作成し、ユーザー空間プログラムに通知します。これにより、デバイス ノードを /dev/ ディレクトリに動的に作成できるようになります。さらに、このメカニズムは、USB フラッシュ ドライブ デバイスをシステムにマウントするように他のアプリケーションに通知することもできるため、デバイスの動的なサポートが実現します。

2. カーネル内の Uevent の場所

次の図は、カーネル内の Uevent モジュールの場所を示しています:

Linuxデバイスモデル(3)_Uevent

Uevent のメカニズムは比較的単純であることがわかり、デバイス モデル内のいずれかのデバイスに報告が必要なイベントがあると、Uevent が提供するインターフェイスがトリガーされます。 Uevent モジュールはイベントを報告するためのフォーマットを準備した後、2 つの方法でイベントをユーザー空間に報告できます: 1 つは kmod モジュールを通じてユーザー空間の実行可能ファイルを直接呼び出す方法、もう 1 つはネットリンク通信を使用する方法です。イベントをカーネル空間からユーザー空間に転送するメカニズムが渡されます。

注 1: Kmod と netlink については他の記事で説明するため、この記事では詳しく説明しません。

3.uevent の内部ロジック分析

3.1 ソースコードの場所

Uevent のコードは比較的単純で、主に次の 2 つのファイル kobject.h と kobject_uevent.c が関係します。

  • include/linux/kobject.h
  • lib/kobject_uevent.c
3.2 データ構造の説明

kobject.h は、uevent 関連の定数とデータ構造を次のように定義します。

    kobject_action
  • rree
kobject_action は、次のようなイベントのタイプを定義します。

#「

ADD/REMOVE、Kobject (または上位データ構造) の追加/削除イベント。

Kobject (または上位層のデータ構造) のオンライン/オフライン イベントである

ONLINE/OFFLINE は、実際にはそれが有効かどうかです。

CHANGE、Kobject (または上位データ構造) の状態または内容が変更されます。

MOVE、Kobject (または上位データ構造) は名前を変更するか、親を変更します (つまり、ディレクトリ構造が sysfs で変更されます)。

CHANGE、デバイス ドライバーが報告する必要があるイベントが上記のイベントの範囲外である場合、またはカスタム イベントである場合は、このイベントを使用して、対応するパラメーターを運ぶことができます。

# kobj_uevent_env
  • rree 前述したように、Kmod を使用してイベントをユーザー空間に報告する場合、ユーザー空間の実行可能ファイルが直接実行されます。 Linux システムでは、実行可能ファイルの実行は環境変数に依存するため、このイベントを報告するときに環境変数を整理するために kobj_uevent_env が使用されます。

#「

envp,指针数组,用于保存每个环境变量的地址,最多可支持的环境变量数量为UEVENT_NUM_ENVP。

envp_idx,用于访问环境变量指针数组的index。

buf,保存环境变量的buffer,最大为UEVENT_BUFFER_SIZE。

buflen,访问buf的变量。

  • kset_uevent_ops
 1: /* include/linux/kobject.h, line 123 */
 2: struct kset_uevent_ops {
 3:     int (* const filter)(struct kset *kset, struct kobject *kobj);
 4:     const char *(* const name)(struct kset *kset, struct kobject *kobj);
 5:     int (* const uevent)(struct kset *kset, struct kobject *kobj,
 6:                         struct kobj_uevent_env *env);
 7: };

kset_uevent_ops是为kset量身订做的一个数据结构,里面包含filter和uevent两个回调函数,用处如下:

filter,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口过滤,阻止不希望上报的event,从而达到从整体上管理的目的。

name,该接口可以返回kset的名称。如果一个kset没有合法的名称,则其下的所有Kobject将不允许上报uvent

uevent,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口统一为这些event添加环境变量。因为很多时候上报uevent时的环境变量都是相同的,因此可以由kset统一处理,就不需要让每个Kobject独自添加了。

3.3 内部动作

通过kobject.h,uevent模块提供了如下的API(这些API的实现是在”lib/kobject_uevent.c”文件中):

 1: /* include/linux/kobject.h, line 206 */
 2: int kobject_uevent(struct kobject *kobj, enum kobject_action action);
 3: int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
 4:                         char *envp[]);
 5:  
 6: __printf(2, 3)
 7: int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
 8:  
 9: int kobject_action_type(const char *buf, size_t count,
 10:                         enum kobject_action *type);

kobject_uevent_env,以envp为环境变量,上报一个指定action的uevent。环境变量的作用是为执行用户空间程序指定运行环境。具体动作如下:

  • kobj 自体またはその親が kset に属しているかどうかを確認します。属していない場合は、エラーが報告されます (注 2: これは、kobject が kset に参加していない場合、uevent を報告できないことを説明できます)
  • kobj->uevent_suppress が設定されているかどうかを確認し、設定されている場合はすべての uevent レポートを無視して戻ります (注 3: Kobject の uevent レポートは Kobject の uevent_suppress フラグを通じて制御できることがわかります)
  • 所属する kset に uevent_ops->filter 関数がある場合、この関数を呼び出してこのレポートをフィルタリングします (注 4: これは、セクション 3.2 のフィルタ インターフェイスの説明をサポートします。kset は、レポートされたくないイベントをフィルタリングできます)全体的な目標を達成するためのフィルタ インターフェイス。管理効果)
  • 属している kset に正式な名前 (以前のカーネル バージョンとは異なるサブシステムと呼ばれる) があるかどうかを確認します。そうでない場合は、uevent
  • を報告することはできません。
  • このレポートの環境変数を格納するバッファを割り当て (結果は env ポインタに保存されます)、sysfs 内の Kobject のパス情報を取得します (ユーザー空間ソフトウェアはパス情報に基づいて sysfs 内のそれにアクセスする必要があります)
  • add_uevent_var インターフェイス (後述) を呼び出して、アクション、パス情報、サブシステム、その他の情報を env ポインターに追加します。 受信した envp が空でない場合は、受信した環境変数を解析し、add_uevent_var インターフェイスも呼び出して、それを env ポインターに追加します。
  • 属している kset に uevent_ops->uevent インターフェイスがある場合は、このインターフェイスを呼び出して、kset 統合環境変数を env ポインターに追加します
  • ACTION のタイプに応じて、kobj->state_add_uevent_sent 変数と kobj->state_remove_uevent_sent 変数を設定して、正しいステータスを記録します
  • add_uevent_var インターフェイスを呼び出し、シリアル番号を「SEQNUM=%llu」
  • の形式で追加します。
  • 「CONFIG_NET」が定義されている場合は、ネットリンクを使用して uevent
  • を送信します。
  • uevent_helper、subsystem、および標準環境変数 (HOME=/、PATH=/sbin:/bin:/usr/sbin:/usr/bin) を持つ env ポインターをパラメーターとして受け取り、kmod モジュールによって提供される call_usermodehelper 関数を呼び出し、uevent を報告します。 。
  • uevent_helper の内容は、カーネル構成項目 CONFIG_UEVENT_HELPER_PATH (./drivers/base/Kconfig にあります) (lib/kobject_uevent.c の 32 行目を参照) によって決定されます。この構成項目はユーザー空間プログラム (またはスクリプト) を指定します。 「/sbin/hotplug」など、報告された uevent を解析するために使用されます。 call_usermodehelper の機能は、プロセスをフォークし、パラメータとして uevent を受け取り、uevent_helper を実行することです。


  • kobject_uevent には、環境変数が指定されていないことを除いて、kobject_uevent_env と同じ機能があります。
  • add_uevent_var は、環境変数をフォーマット文字の形式で env ポインターにコピーします (printf、printk などと同様)。

kobject_action_type、enum kobject_action 型のアクションを文字列に変換します。

#説明: uevent を処理するユーザー空間プログラム (略して uevent ヘルパー) を指定するにはどうすればよいですか?

上記の kobject_uevent_env の内部アクションを紹介するときに、Uevent モジュールが Kmod を通じて Uevent を報告するときに、ユーザー空間の実行可能ファイル (または \**uevent helper\* と呼ばれるスクリプト) を呼び出すと述べました。 call_usermodehelper 関数を使用して *) イベントを処理します。 uevent ヘルパーのパスは \**uevent_helper 配列に保存されます。

カーネルのコンパイル時に、CONFIG_UEVENT_HELPER_PATH 構成項目を通じて uevent ヘルパーを静的に指定できます。ただし、この方法はイベントごとにプロセスをフォークするため、カーネルがサポートするデバイスの数が増えると、システム起動時に致命的になります(メモリオーバーフローなどを引き起こす可能性があります)。したがって、この方法は初期のカーネル バージョンでのみ使用されており、カーネルでは現在推奨されていません。したがって、カーネルをコンパイルするときは、この設定項目を空白のままにする必要があります。

システムが起動すると、ほとんどのデバイスの準備が整います。システム動作中にホット プラグ イベントを検出するために、必要に応じて uevent ヘルパーを再割り当てできます。これは、ヘルパー パスを「/sys/kernel/uevent_helper」ファイルに書き込むことで実現できます。実際、カーネルは、ユーザー空間プログラムの変更とアクセスのために、sysfs ファイル システムを通じて uevent_helper 配列をユーザー空間に開きます。詳細については、「\*\*\*\*./kernel/ksysfs.」内の対応するコードを参照してください。 c" については、ここでは詳しく説明しません。

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

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