kobject/sysfs(1)

カーネル2.5/2.6では、従来ソースのデバイスドライバもサポートしながら、新しいドライバモデルが導入されて、Hotplugやパワーマネジメントを始め、新しいバス・アーキテクチャに対応するための、様々な試みが行われている。今回からは、以前予告したように、この新しいドライバモデルの核となる、sysfsとkobjectの内容と実態について、簡単に解説していく。

kobject インフラストラクチャ

Patrick Mochelを中心としたメンバによって、新しいドライバモデルの導入が推進されているが、カーネル2.5.71からは、kobjectを知る上での手がかりとなる、Documens/kobject.txtが少々だが久しぶりに書き直された。そこで、このkobject.txtの内容を紹介しながら、何回かに分けてkobjectの実態とsysfsとの関係、2.5系カーネルにおけるkobjectを使用したローダブル・モジュールやデバイスドライバの開発方法に関して取り上げる。

0. 序文

kobjectインフラストラクチャは、より大きいデータ構造とサブシステムが介入することができる、基本的オブジェクト管理を実行する。この機能は、主に次に関わる:

  • オブジェクト・リファレンスのカウント
  • リストやセットになったオブジェクトのメンテナンス
  • オブジェクト・セットのロック
  • ユーザスペースでの表現

このインフラは、機能を支えるために多くのオブジェクトの型から成り、プログラミングインタフェイスは、以下に基づいて記述される:

1 kobject 単純なオブジェクト
2 ksets 特定のタイプの一組のオブジェクト
3 ktype 一般タイプのオブジェクトのための一組のヘルパー
4 subsystem 多くのksetsのために制御しているオブジェクト

kobjectインフラストラクチャは、sysfsファイルシステムとの密接な関係を維持していて、kobjectのコアで登録される各kobjectは、sysfsから該当する登録用ディレクトリを受ける。kobjectに関するアトリビュートは、エクスポートすることができる。sysfsに関する詳細はDocumentation/filesystems/sysfs.txtに記述されている。

kobjectインフラストラクチャが提供するプログラミングインタフェイスでは、後述するように、sysfsを意識せずにkobjectsとksetsを登録できる。

1. kobjects

1.1 説明

struct kobjectは、より複雑なオブジェクト型に提供するための単純で基本的なデータ型である。それは多くの複雑なデータ型が共有する一組の基本的なフィールドを提供する。kobjectsはより大きなデータ構造(struct)の中に埋め込まれて、それらが複製するフィールドを置き換えるようになっている。

1.2 定義

struct kobject {
	char			name[KOBJ_NAME_LEN];
	atomic_t		refcount;
	struct list_head	entry;
	struct kobject	* parent;
	struct kset		* kset;
	struct kobj_type	* ktype;
	struct dentry		* dentry;
};

void kobject_init(struct kobject *);
int kobject_add(struct kobject *);
int kobject_register(struct kobject *);

void kobject_del(struct kobject *);
void kobject_unregister(struct kobject *);

struct kobject * kobject_get(struct kobject *);
void kobject_put(struct kobject *);

1.3 kobject プログラミングインタフェイス

kobjectsは、kobject_register()とkobject_unregister()によって、kobjectコアからダイナミックに追加または削除される。追加登録時には、kobjectをそれに適合するksetのリストに挿入して、sysfsでの必要なディレクトリの作成動作を含む。

kobject_init()の呼び出しでは、kobjectをksetのリストに加える事をせずに使用するか、sysfsを通してエクスポートする事無く使用することもできる。初期化されたkobjectは、kobject_add()を呼ぶことによって後でオブジェクト階層に加える事ができる。初期化されたkobjectは、リファレンス・カウントに使用しても良い。

注意: kobject_init()呼出し後にkobject_add()を呼ぶことは、機能的にkobject_register()を呼ぶ事に等しい。

kobject_unregister()は、kobjectをksetのリスト(sysfsファイルシステムから取り除かれる)から取り除かれる。その後、その参照カウントは減少させられる。sysfsからのリストと削除動作はkobject_del()によって起こされる。この動作はkobject_add()の呼び出しに対応する形で、マニュアルで呼び出してもよい。kobject_put()は参照カウントを減少させる。これもまた、マニュアルで呼び出し可能である。

kobjectの参照カウントはkobject_get()で増加させることも可能であり、kobject_put()で減少させた場合を含めて、それらの呼び出しでは、kobjectに有効なリファレンスを返す。オブジェクトの参照カウントは、正である場合にだけ、増加させる事ができる。

オブジェクトの参照カウントがゼロに達した時には、kobjectのksetが指し示している、kobj_type::release() メソッドが呼ばれる。これは、オブジェクトに割り当てられているあらゆるメモリを解放させてしまう。

注意!!!

動的に獲得したkobjectを解放するためのデストラクタを用意することは、kobjectの参照カウントを使用する場合に「避けて通れない」。参照カウントは、kobjectの存続する有効期間を制御する。カウントがゼロであれば、オブジェクトが解放されて、使われないと判定される。

最も重要なことは、そこでオブジェクトを解放しなければならず、unregisterの直後では無いということである。ほかの誰かが、(例えばsysfsファイルを使用して)オブジェクトを参照して、そのオブジェクトへの参照を獲得しようとしているときに、それが有効であれば操作するかも知れない。もしオブジェクトが登録されてなく、それまでの間に解放されていたならば、その操作は解放されたメモリを参照して、どこかに行ってしまう。

release() メソッドを定義する事により、オブジェクトだけを解放することによる最も単純な場合は、これを防ぐことができる。これは、この参照カウント/オブジェクト管理モデルでは、二重参照カウントやその他のネットワークでの参照カウントのような予想されないケースでは、安全ではない点に注意する必要がある。

1.4 sysfs

各kobjectは、sysfsによってディレクトリを受けとる。このディレクトリは、kobjectの親ディレクトリの下に作成される。登録時に、kobjectに親が無い場合、その親はその支配的なksetになる。

kobjectに親も支配的なksetも無い場合は、そのディレクトリはsysfsのパーティションの中でトップレベルのものとして作成される。これは、subsystemの構成として埋め込まれるkobjectsのために行われる。

<筆者によるここまでの解説>

現在、全てのsysfsのインタフェイスと、一部のkobjectや関連するシンボルは、実際には外部モジュール用にエクスポートされていないため、外部モジュールからの呼び出しや参照はできない。ここまでの、kobjectに関する解説は、kobjectの構造とドライバモデルの基本を理解という意味では非常に重要であるが、実際のデバイスドライバやシステム・モジュールの開発では、上記のインタフェイスはほとんど使用されることは無いと思われる。開発に必要なプログラミング・インタフェイスは上記とは別に、目的に応じて用意されている。

例えば(一般的には不必要であるが)上記のインタフェイスを使って、sysfsのディレクトリの配下の好きな場所にディレクトリやファイルを作成したり、kobjectを登録するためには、現状ではカーネルにスタティックにリンクするルーチンの中で行うか、独自にインタフェイスをエクスポートさせるしかない。

また、次回以降で解説予定であるが、この自由にsysyfsツリーを直接操作できない事と、sysfsの(支配的な)トップレベルにクラス、バス、デバイス、ドライバといった、各目的別のプログラミングインタフェイスを用意して、それを、ローダブル・モジュールのプログラマに使用させる事は、sysfsツリーの構成にセキュリティと秩序を与える事となっている。kobjectの解説の続きであるksets, ktype, subsystem に関しては次回以降で解説する。