総合手引 | セクション 9 | English | オプション |
#include <sys/types.h>
#include <sys/sysctl.h>
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 を返します。
#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"); ... oidp = SYSCTL_ADD_NODE( &clist, SYSCTL_STATIC_CHILDREN(_debug), 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"); ... /* ここで oid を解放できます */ if(sysctl_ctx_free(&clist)) { printf("コンテキストを解放出来ません - 他の oid が依存しています"); return(ENOTEMPTY); } else { printf("成功です! ): return(0); }
この使用例は以下のサブツリーを作成します。
debug.newtree.newstring newtree.newint
1 つの sysctl_ctx_free() の呼び出しを通して、両方のツリーが削除され、 リソースが解放されることに注意してください。 最新のエントリ (葉) を解放することによって始まり、それから 古いエントリ (この場合はノード) の削除を続行します。
コンテキスト上の全ての操作はリンクリストを横切ることを必要とします。 この理由のため、エントリの作成と削除には相対的にコストがかかります。
SYSCTL_CTX_INIT (9) | July 15, 2000 |
総合手引 | セクション 9 | English | オプション |
このマニュアルページサービスについてのご意見は Ben Bullock にお知らせください。 Privacy policy.
“ | Do you laugh when the waiter drops a tray full of dishes? Unix weenies do. They're the first ones to laugh at hapless users, trying to figure out an error message that doesn't have anything to do with what they just typed. | ” |
— The Unix Haters' handbook |