SYSCTL_CTX_INIT(9) FreeBSD カーネル開発者マニュアル SYSCTL_CTX_INIT(9)
名称
sysctl_ctx_init, sysctl_ctx_free, sysctl_ctx_entry_add, sysctl_ctx_entry_find, sysctl_ctx_entry_del − 動的に生成された sysctl oid のための sysctl コンテキスト |
書式
#include <sys/types.h> int |
sysctl_ctx_init(struct sysctl_ctx_list *clist); int
sysctl_ctx_free(struct sysctl_ctx_list *clist); struct sysctl_ctx_entry * struct sysctl_ctx_entry * int 解説 |
これらの関数は動的に作成された oid の管理のためのインタフェースを提供しま す。 sysctl コンテキストは作成された oid の必要な時の厳密な削除はもちろ ん、 oid を見失わないようにすることに対して責任があります。これは oid の 削除操作に簡単なトランザクション的な側面を追加します。すなわち、途中で削 除操作が失敗した場合に、sysctl ツリーを以前の状態にロールバックすることが 可能です。 sysctl_ctx_init() 関数は sysctl コンテキストを初期化します。 clist 引数は 既に割り当てられている変数を指していなければなりません。コンテキストは使 用の前に 必ず初期化されていなければなりません。一度初期化されると、そのコ ンテキストのポインタは全ての SYSCTL_ADD_* マクロ (sysctl_add_oid(9) 参照) の引数として渡されることが可能で、新しく作成される oid を指すエントリを 伴って更新されるでしょう。 内部的には、コンテキストは queue(3) TAILQ リンクリストとして表現されてい ます。そのリストは struct sysctl_ctx_entry エントリから成っています。 struct sysctl_ctx_entry { |
struct sysctl_oid *entry; |
||
TAILQ_ENTRY(sysctl_ctx_entry) link; |
}; TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); 各々のコンテキストエントリは、それが管理する 1 つの動的な oid を指しま す。新しく作成された oid は常にリストの最初に挿入されます。 sysctl_ctx_free() 関数はコンテキストおよびそれが管理する関連付けられた oid を削除します。その関数が成功して完了した場合には、全ての管理されてい る oid は登録抹消 (ツリーから削除) され、全てのそれらに割り当てられたメモ リと共に解放され、同様にコンテキストのエントリも解放されています。 削除操作は 2 ステップで実行されます。最初に、各々のコンテキストエントリの ために、リソースの解放を抑制するパラメータ del を 0 に設定して、関数 sysctl_remove_oid(9) が呼び出されます。このステップでエラーが無い場合に は、 sysctl_ctx_free() は次のステップに移行します。最初のステップが失敗し た場合には、そのコンテキストに関連付けられた全ての登録抹消された oid が再 登録されます。 注意: ほとんどの場合、プログラマは oid の作成時に oid 番号として OID_AUTO を明示します。しかしながら、ツリーに oid を登録している間に、この番号は 99 よりも大きい最初の利用可能な番号に変更されます。コンテキスト削除の最初 のステップが失敗した場合、 oid の再登録は既に割り当てられている oid 番号 を変更しません (OID_AUTO とは異なります)。これは、再登録されたエントリが ツリーの中の元の位置を維持していることを保証します。 2 番目のステップは、動的な oid の削除を実際に実行します。 sysctl_remove_oid(9) は最初 (すなわち、最新のエントリ) から始めて、コンテ キストリストを通して繰り返します。 重要: この時、この関数はツリーから oid を削除するだけではなく、全てのコンテキストのメモリはもちろ ん、(oid_refcount == 0 であれば) oid のメモリも解放します。 sysctl_ctx_entry_add() 関数は既存の動的な oid のコンテキストへの追加を可 能にします。 sysctl_ctx_entry_del() 関数はコンテキストからエントリを取り除きます。 重 要: この場合、対応する struct sysctl_ctx_entry のみが解放されますが、 oidp ポインタはそのまま残ります。その後は、プログラマにこの oid に割り当 てられたリソースの管理の責任があります。 sysctl_ctx_entry_find() 関数は与えられた oidp をコンテキストリストの中か ら検索し、見付かった struct sysctl_ctx_entry へのポインタまたは NULL を返 します。 |
使用例
以下は、どのように新しいトップレベルのカテゴリを作成するか、およびどのよ うに既存の静的なノードに別のサブツリーを引っ掛けるかを示す使用例です。こ の使用例は oid の追跡を維持するためにコンテキストを使用しています。 #include <sys/sysctl.h> ... struct sysctl_ctx_list clist; struct sysctl_oid *oidp; int a_int; char *string = "dynamic sysctl"; ... sysctl_ctx_init(&clist); oidp = SYSCTL_ADD_NODE( &clist, SYSCTL_STATIC_CHILDREN(/* ツリートップ */), |
OID_AUTO, "newtree", CTFLAG_RW, 0, "new top level tree"); |
oidp = SYSCTL_ADD_INT( &clist, SYSCTL_CHILDREN(oidp), |
OID_AUTO, "newint", CTLFLAG_RW, &a_int, 0, "new int leaf"); |
... |
OID_AUTO, "newtree", CTFLAG_RW, 0, "new tree under debug"); |
oidp = SYSCTL_ADD_STRING( &clist, SYSCTL_CHILDREN(oidp), |
OID_AUTO, "newstring", CTLFLAG_R, string, 0, "new string leaf"); |
... |
printf("コンテキストを解放出来ません - 他の oid が依存しています"); |
|
return(ENOTEMPTY); |
} else { |
printf("成功です!\n"): |
|
return(0); |
} この使用例は以下のサブツリーを作成します。 debug.newtree.newstring newtree.newint 1 つの sysctl_ctx_free() の呼び出しを通して、両方のツリーが削除され、リ ソースが解放されることに注意してください。最新のエントリ (葉) を解放する ことによって始まり、それから古いエントリ (この場合はノード) の削除を続行 します。 |
関連項目
queue(3), sysctl(8), sysctl_add_oid(9), sysctl_remove_oid(9) |
歴史
これらの関数は FreeBSD 4.2 ではじめて登場しました。 |
作者
Andrzej Bialecki 〈abial@FreeBSD.org〉 |
バグ
現在の削除アルゴリズムは多少重いです。最悪の場合、全ての oid が登録抹消さ れ、再登録され、それから登録抹消され、削除される必要があります。しかしな がら、削除操作がトランザクションの特質を持つことを、このアルゴリズムは保 証します。 コンテキスト上の全ての操作はリンクリストを横切ることを必要とします。この 理由のため、エントリの作成と削除には相対的にコストがかかります。 FreeBSD 10.0 July 15, 2000 FreeBSD 10.0 |