SYSCTL_ADD_OID(9)

名称
sysctl_add_oid, sysctl_move_oid, sysctl_remove_oid - ランタイム sysctl ツリー操作

書式
<sys/types.h> <sys/sysctl.h> struct sysctl_oid * sysctl_add_oid(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int kind, void *arg1, int arg2, int (*handler) (SYSCTL_HANDLER_ARGS), const char *format, const char *descr) int sysctl_move_oid(struct sysctl_oid *oidp, struct sysctl_oid_list *parent) int sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse) struct sysctl_oid_list * SYSCTL_CHILDREN(struct sysctl_oid *oidp) struct sysctl_oid_list * SYSCTL_STATIC_CHILDREN(struct sysctl_oid_list OID_NAME) struct sysctl_oid * SYSCTL_ADD_OID(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int kind, void *arg1, int arg2, int (*handler) (SYSCTL_HANDLER_ARGS), const char *format, const char *descr) struct sysctl_oid * SYSCTL_ADD_NODE(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, int (*handler) (SYSCTL_HANDLER_ARGS), const char *descr) struct sysctl_oid * SYSCTL_ADD_STRING(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, char *arg, int len, const char *descr) struct sysctl_oid * SYSCTL_ADD_INT(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, int *arg, int len, const char *descr) struct sysctl_oid * SYSCTL_ADD_UINT(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, unsigned int *arg, int len, const char *descr) struct sysctl_oid * SYSCTL_ADD_LONG(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, long *arg, const char *descr) struct sysctl_oid * SYSCTL_ADD_ULONG(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, unsigned long *arg, const char *descr) struct sysctl_oid * SYSCTL_ADD_OPAQUE(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, void *arg, int len, const char *format, const char *descr) struct sysctl_oid * SYSCTL_ADD_STRUCT(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, void *arg, STRUCT_NAME, const char *descr) struct sysctl_oid * SYSCTL_ADD_PROC(struct sysctl_ctx_list *ctx, struct sysctl_oid_list *parent, int number, const char *name, int access, void *arg1, int arg2, int (*handler) (SYSCTL_HANDLER_ARGS), const char *format, const char *descr)

解説
これらの関数およびマクロは sysctl oid のランタイム (例えばモジュールの 存在期間) での作成と削除のためのインタフェースを提供します。 リンカセット (詳細は <sys/linker_set.h> および src/sys/kern/kern_sysctl.c を参照) に基づく代わりの方法は、各々のモジュールのロード時およびアンロード時の 作成と削除のみを可能にします。

型 CTLTYPE_NODE の動的な oid は再利用可能であるため、複数のコードセクションが、 oid を作成および削除することが可能です。 実際には、参照カウントに基づいて、その割り当ておよび解放が行われます。 その結果として、2 つ以上のコードセクションが、部分的に重なり、 両者が使用できるツリーを作成可能にします。 重なる葉の作成や、同一の名前と親を持つ異なる型の子の作成は、 不可能です。

新しく作成された oid は親のノードに接続されます。 これら全ての関数およびマクロ ((sysctl_remove_oid) は例外) において、必須パラメータの 1 つ parent は、子の親リストの先頭を指します。

殆どのトップレベルのカテゴリは静的に作成されます。 既存の静的な oid に接続するときに、このポインタは SYSCTL_STATIC_CHILDREN() マクロによって取得することが可能で、その OID_NAME 引数は CTLTYPE_NODE 型の親 oid の名前 (すなわち、 sysctl(8) によって表示される名前に、 アンダスコアを前置し、全てのドットをアンダスコアで置き換えた名前) です。

既存の動的な oid に接続するときに、このポインタは SYSCTL_CHILDREN() マクロによって取得することが可能で、その oidp 引数は CTLTYPE_NODE 型の親 oid を指します。

sysctl_add_oid() 関数はあらゆる型の生の oid を作成します。 oid の作成が成功した場合には、この関数はその oid へのポインタを返します。 そうでない場合には、 NULL を返します。 sysctl_add_oid() のための引数の多くはマクロと共通です。 引数は以下のとおりです。

ctx オプションの sysctl コンテキストへのポインタ、または NULL です。 詳細は sysctl_ctx_init(9) を参照してください。 特別な作成および削除のシーケンスが要求されるのでなければ、 作成する動的な oid を組織するためにコンテキストを使用することを、 プログラマは強く勧告されています。 ctx が NULL でない場合には、新しく作成される oid は最初のエントリとしてこのコンテキストに 追加されます。

parent
    子の親リストの先頭である struct sysctl_oid_list へのポインタです。

number
    この oid に割り当てられる oid 番号です。 殆ど全ての場合、これは割り当て時に次の利用可能な oid 番号になる OID_AUTO に設定されるべきです。

name
    この oid の名前です。 新しく作成された oid は名前のコピーを含んでいます。

kind
    oid の種類で、 <sys/sysctl.h> ヘッダファイルの中で定義される型とアクセス値のビットマスクとして明示されます。 動的に作成された oid は常に CTLFLAG_DYN フラグが設定されます。 アクセスフラグはこの oid が読み取り専用か読み書き可能か、および 全てのユーザによってまたはスーパユーザによってのみ修正可能かを明示します。

arg1
    oid が参照すべきあらゆるデータへのポインタ、または NULL です。

arg2
    arg1 の大きさ、または arg1 が NULL であれば 0 です。

handler
    この oid への読み書き要求を取り扱う責任がある関数へのポインタです。 ノード、整数、文字列、および不透明なオブジェクトの操作をサポートする 幾つかの標準ハンドラが存在しています。 SYSCTL_ADD_PROC() マクロを使用して新しいハンドラを定義することも可能です。

format
    oid のフォーマットを記号的に明示する文字列へのポインタです。 このフォーマットは、表示目的のための適切なデータフォーマットを適用するために sysctl(8) によってヒントとして使用されます。 現在使用されているフォーマット名は以下のとおりです。 “N” はノード、 “A” は char * 型、 “I” は int 型、 “IU” は unsigned int 型、 “L” は long 型、 “LU” は unsigned long 型、および “S,TYPE” は struct TYPE 構造体です。

descr
    この oid の解説テキストへのポインタです。

sysctl_move_oid() 関数は存在している oid の親を付け変えます。 その oid は、まるで number に OID_AUTO が設定されて作成されたかの様に、新しい番号を割り当てられます。

sysctl_remove_oid() 関数は動的に作成された oid をツリーから削除し、 オプションでそのリソースを解放します。 これは以下の引数を取ります。

oidp
    削除されるべき動的な oid へのポインタです。 oid が動的でない、またはポインタが NULL の場合には、この関数は EINVAL を返します。

del 0 でない場合には、oid の参照カウントが 0 になった時に、 sysctl_remove_oid() は oid のリソースを解放しようとします。 しかしながら del が 0 に設定されている場合には、このルーチンは oid のリソースの解放をせずに ツリーから oid の登録抹消のみを行ないます。 この振舞いは、呼び出し側が後で (ひょっとすると部分的に失敗する) 多数の oid の 削除のロールバックを予期している時に、有用です。

recurse
    0 でない場合には、そのノードとその子を削除しようとします。 recurse が 0 に設定されている場合には、あらゆる子を含むノードの削除の試みは ENOTEMPTY エラーを発生させます。 警告: 再帰的な削除は非常な注意を払って使用すること! 通常、コンテキストが使用されていれば、必要とされるべきではありません。 コンテキストはツリーの利用者間の依存性の追跡に注意しています。 しかしながら、ある極端な場合には、ある他のリソースを解放するために、 それがどのように作成されたものであれ、サブツリーの一部を削除することが 必要になることがあります。 しかしながら、このことは、別のコードセクションが削除されたサブツリーを 使用し続ける場合に、システムの panic(9) を引き起こすことがあることを知っていてください。

再度言いますが、殆んどの場合、作成された oid を見失わないようにするため、 および後で整然とした流儀でそれらを削除するため、 sysctl_ctx_init(9) で解説されているように、プログラマはコンテキストを使用するべきです。

与えられた型の oid の作成を助ける定義済みのマクロセットがあります。
それらを以下に示します。

SYSCTL_ADD_OID()
    は生の oid を作成します。 このマクロは機能的には sysctl_add_oid() 関数と同等です。

SYSCTL_ADD_NODE()
    は型 CTLTYPE_NODE の oid を作成します。 この oid に対して、子の oid を追加可能です。

SYSCTL_ADD_STRING()
    は 0 で終端された文字列を取り扱う oid を作成します。

SYSCTL_ADD_INT()
    は int 変数を取り扱う oid を作成します。

SYSCTL_ADD_UINT()
    は unsigned int 変数を取り扱う oid を作成します。

SYSCTL_ADD_LONG()
    は long 変数を取り扱う oid を作成します。

SYSCTL_ADD_ULONG()
    は unsigned long 変数を取り扱う oid を作成します。

SYSCTL_ADD_OPAQUE()
    は size_t * へのポインタである len 引数によって明示された大きさのあらゆる不透明なデータのかたまりを 取り扱う oid を作成します。

SYSCTL_ADD_STRUCT()
    は struct TYPE 構造体を取り扱う oid を作成します。 format 引数は sysctl(8) ユーティリティへの適切なヒントを提供するために “S,TYPE” に設定されます。

SYSCTL_ADD_PROC()
    は明示された handler ハンドラ関数を持つ oid を作成します。 ハンドラは oid に対しての読み書き要求を取り扱う責任を持ちます。 カーネルデータが簡単にアクセスできない場合、または取り出される前に処理される 必要がある場合に、この oid 型は特に有用です。

使用例
以下は、どのように新しいトップレベルのカテゴリを作成するか、および どのように既存の静的なノードに別のサブツリーを引っ掛けるか を示す使用例です。 この使用例はコンテキストを使用していません。 これは全ての後でそれらを解放するといった、 中間の oid の退屈な管理を結果として生じさせます。

    #include <sys/sysctl.h>
     ...
    /* 新しく作成したサブツリーへのポインタは、後でそれらを解放するために
     * 保存しておく必要があります。
     */
    struct sysctl_oid *root1, *root2, *oidp;
    int a_int;
    char *string = "dynamic sysctl";
     ...
    root1 = SYSCTL_ADD_NODE( NULL, SYSCTL_STATIC_CHILDREN(/* tree top */),
    	OID_AUTO, "newtree", CTLFLAG_RW, 0, "new top level tree");
    oidp = SYSCTL_ADD_INT( NULL, SYSCTL_CHILDREN(root1),
    	OID_AUTO, "newint", CTLFLAG_RW, &a_int, 0, "new int leaf");
     ...
    root2 = SYSCTL_ADD_NODE( NULL, SYSCTL_STATIC_CHILDREN(_debug),
    	OID_AUTO, "newtree", CTLFLAG_RW, 0, "new tree under debug");
    oidp = SYSCTL_ADD_STRING( NULL, SYSCTL_CHILDREN(root2),
    	OID_AUTO, "newstring", CTLFLAG_RD, string, 0, "new string leaf");

この使用例は以下のサブツリーを作成します。

    debug.newtree.newstring
    newtree.newint

これ以上必要でなくなった全ての oid は解放されるべきであることに注意!

関連項目
sysctl(8), sysctl_ctx_free(9), sysctl_ctx_init(9)

歴史
これらの関数は FreeBSD 4.2 ではじめて登場しました。

作者
Andrzej Bialecki <abial@FreeBSD.org>

バグ
多くのコードセクション間でノードを共有することは、 時々リソースをロックすることがある相互依存を引き起こします。 例えば、モジュール B によって作成された oid に対し、 モジュール A がサブツリーを引っ掛けた場合には、 モジュール B はその oid を削除できないでしょう。 これらの問題は sysctl コンテキストによって適切に取り扱われます。

ツリー上の多くの操作はリンクリストを横切ることを必要とします。 この理由のため、oid の作成と削除は相対的にコストがかかります。