新しいカーネル・サブシステムの作成,あるいは既存のカーネル・サブシステムの変更を行う場合,それらを動的に構成可能なように設定することができます。 付録 C では,以下の情報を提供することにより,動的に構成可能なカーネル・サブシステムの作成方法について説明します。
動的に構成可能なサブシステムについての概要 (C.1 節)
属性テーブルについての概要と属性テーブルの例 (C.2 節)
構成ルーチンの作成方法と構成ルーチンの例 (C.3 節)
オペレーティング・システムとサブシステムとで互換性があるかどうかを確認するためのオペレーティング・システムのバージョンのチェック方法 (C.4 節)
テストのために,ロード可能なサブシステムをカーネルに組み込む方法 (C.5 節)
テストのために,実行時に属性の変更を可能にするスタティック・サブシステムをカーネルに組み込む方法 (C.6 節)
動的に構成可能なサブシステムのデバッグに関する情報 (C.7 節)
Tru64 UNIX オペレーティング・システムが動的に構成可能なサブシステムをサポートする以前は,それらのシステムの構成ファイルをシステム管理者が編集することによりカーネル・サブシステムを管理していました。 この方法では,サブシステムの追加/変更,あるいはサブシステム・パラメータの変更の際に,場合によっては複雑で時間のかかる,カーネルの再構築が必要でした。 複数のシステムを管理しているシステム管理者は,それらのシステムの各構成ファイルに対して変更を加え,それぞれのカーネルを再構築する必要がありました。
動的に構成可能なサブシステムのサポートによって,システム管理者は,ファイルの編集やカーネルの再構築をせずにシステム・パラメータの変更やサブシステムのロード/アンロードを行うことができます。
システム管理者は,sysconfig
コマンドを使用することによりカーネルのサブシステムを構成することができます。
このコマンドを使用することにより,システム管理者は,サブシステムのロードおよび構成,アンロードおよび構成除外,再構成 (変更),および照会をローカル・システムあるいはリモート・システムで行なうことができます。
ロード可能なデバイス・ドライバを作成する場合は,デバイス・ドライバ固有の問題について考慮する必要があります。
ロード可能なデバイス・ドライバの作成方法については,『Writing Device Drivers』を参照してください。
C.1 動的に構成可能なサブシステムの概要
多くの Tru64 UNIX カーネル・サブシステムはスタティック・サブシステムであるため,構築時にカーネルとリンクされています。
カーネルを構築した後は,これらのサブシステムをロードあるいはアンロードすることはできません。
スタティック・サブシステムの例としては,vm
(virtual memory: 仮想メモリ) サブシステムが挙げられます。
このサブシステムはシステムが正く動作するために必要なものです。
カーネル・サブシステムによってはロード可能なものもあります。
ロード可能なサブシステムは,カーネルを再構築せずにカーネルに対してサブシステムを追加/削除することができます。
ロード可能なサブシステムの例としては,presto
サブシステムが挙げられます。
presto
サブシステムは,Prestoserve ソフトウェアを使用している場合のみロードされます。
スタティック・サブシステムおよびロード可能なサブシステムのどちらも,動的に構成することができます。
スタティック・サブシステムの場合,動的に構成可能であるということは,カーネルを再構築しなくても選択したサブシステムの属性が変更できることを意味します。 このタイプのサブシステムは,属性値に関する照会に応答することが可能で,使用中でなければ構成除外することもできます (ただし,アンロードすることはできません)。
ロード可能なサブシステムの場合,動的に構成可能であるということは,ロード時にサブシステムがカーネルに構成され,カーネルを再構築せずにサブシステムの変更が可能で,また,アンロードする前にサブシステムの構成が除外されることを意味します。 このタイプのサブシステムは,属性に関する照会に応答することができます。
従来のカーネル・サブシステムと同じように,動的に構成可能なサブシステムはパラメータを持っています。 これらのパラメータは属性と呼ばれます。 サブシステムの属性の例としては,タイムアウト値,テーブル・サイズ,メモリ位置,サブシステム名などがあります。 サブシステムの属性は属性テーブルに定義します。 属性テーブルについてはC.2 節を参照してください。
ロード可能サブシステムを最初に構成する前に,システム管理者は属性に対する値を
sysconfigtab
データベースに保管することができます。
このデータベースは
/etc/sysconfigtab
ファイルに保管され,ブート時にカーネル・メモリにロードされます。
このデータベースに保管された値は,サブシステムがその属性の初期値を供給しているかどうかにかかわらず,サブシステムの属性の初期値になります。
図 C-1
は,どのようにして
sysconfigtab
データベースから初期属性値が得られるかを示しています。
図 C-1: システム属性値の初期化
図 C-1
で,サブシステムが
size
属性の値を 0 (ゼロ) に初期化しているにもかかわらず,size
属性の初期値として
sysconfigtab
データベースの値が割り当てられていることに注意してください。
サブシステム・コードで宣言されている属性テーブルを使用するには,最初の構成時にどちらのサブシステム属性値を設定できるかを制御します。
sysconfigtab
データベースに設定できる属性を制御する方法については,C.2 節を参照してください。
最初の構成時のための属性値を保管できることに加えて,システム管理者は,サブシステムがカーネルに構成されている場合はいつでもその属性値の照会や再構成が可能です。 照会要求に対しては,システム管理者に属性値が返されます。 再構成要求の場合は,属性値は変更されます。 これらの処理は,属性がサブシステム・コードでどのように宣言されているかに依存します。
サブシステムの属性テーブルが属性のアドレスをカーネルに供給している場合,カーネルがその属性値の変更あるいは照会に対する応答を行うことができます。 カーネルにアドレスを供給し,カーネルが属性値を処理できるようにすることは,属性値を保守する最も効果的な方法です。
カーネルがその属性値へアクセスできない場合は,サブシステムが属性値の変更あるいは照会への応答を行う必要があります。 カーネルが属性値を処理できるようにするのが属性値を保守する最も効果的な方法ですが,サブシステムが属性値を保守せざるを得ない場合もあります。 たとえば,カーネルは属性値を計算することはできませんので,計算が必要な値の保守はサブシステムが行なう必要があります。
サブシステムのどの属性値に対する照会あるいは再構成を可能にするかについては,C.2 節に示す方法で制御します。
動的に構成可能な各サブシステムは,属性テーブルに加えて構成ルーチンも使用します。 このルーチンは,サブシステムで保守する属性値の計算などのタスクを行います。 また,たとえばテーブルの大きさの決定,あるいはサブシステムが使用するローカル変数のメモリ位置の保管などのサブシステム固有のタスクも実行します。 C.3 節で,構成ルーチンの作成方法について説明します。 カーネルは,サブシステムが構成,照会,再構成,あるいは構成除外されるたびにサブシステムの構成ファイルを呼び出します。
カーネルに構成できるサブシステムは,カーネル構成から除外することもできます。
システム管理者がカーネル構成からサブシステムを除外すると,そのサブシステムに占有されていたカーネル・メモリは,サブシステムがロード可能な場合には解放されます。
構成除外要求の際にカーネルがサブシステム構成ルーチンを呼び出すことにより,サブシステムはサブシステム固有の構成除外タスクを実行することができます。
サブシステム固有の構成除外タスクの例としては,サブシステム・コードによって割り当てられたメモリの解放があります。
C.2 属性テーブルの概要
動的に構成可能な効果的なサブシステムを作成するポイントは,効果的な属性テーブルを定義することです。 属性テーブルはサブシステムの属性を定義します。 属性の例としては,タイムアウト値,テーブル・サイズ,メモリ位置などがあります。 属性テーブルは,定義属性テーブルと通信属性テーブルの 2 つのフォーマットで存在します。
定義属性テーブルはサブシステム・コードに含まれています。 この属性テーブルは,そのサブシステムの属性を定義します。 各属性の定義は,属性テーブル構造体の 1 つの要素です。 この定義には,属性名,属性のデータ型,システム管理者がその属性に対して行うことができる要求リストが含まれます。 各属性の定義には,最小値,最大値,また,オプションでそれらの保管領域も含まれます。 カーネルは,構成,再構成,照会,構成除外などのシステム管理者からの要求に応答するために属性の定義を使用します。
通信属性テーブルはカーネルとサブシステム・コードの通信に使用されます。 この属性テーブル構造体の各要素は,1 つの属性の情報を媒介します。 この情報には,次のものが含まれます。
属性の名前とデータ型
その属性に対して行われた要求
要求の状態
属性の値
この属性テーブルは,システム管理者が構成,再構成,照会,あるいは構成除外などの要求を行ったときにカーネルからサブシステムへ渡されます。
2 つのタイプの属性テーブルを使用するのは,カーネル・メモリを節約するためです。 定義属性テーブルの情報のいくつか (たとえば,属性名,属性のデータ型など) は通信属性テーブルの情報と同じですが,情報の多くはそれぞれのテーブルで異なります。 たとえば,属性定義時には要求は発生しないので,定義属性テーブルには要求の状態は保管しません。 同様に,通信属性テーブルには,各属性に対する要求のサポート・リストは含まれません。 カーネル・メモリを節約するために,各属性テーブルには必要な情報のみが含まれます。
注意
サブシステム属性テーブルに定義されている属性名は,文字列
method
で始まっていてはなりません。 この文字列は,ロード可能デバイス・ドライバ・メソッドで使用されるネーミング属性のために予約されています。 デバイス・ドライバ・メソッドについての詳細は,『Writing Device Drivers』を参照してください。
以降の各項で,/sys/include/sys/sysconfig.h
における宣言を示しながら,両方のタイプの属性テーブルについて説明します。
C.2.1 定義属性テーブル
定義属性テーブルには,データ型
cfg_subsys_attr_t
が含まれています。
これは,/sys/include/sys/sysconfig.h
ファイルで次のように宣言されている属性の構造体です。
typedef struct cfg_attr { char name[CFG_ATTR_NAME_SZ]; [1] uint type; [2] uint operation; [3] whatever address; [4] uint min; [5] uint max; uint binlength; [6] }cfg_subsys_attr_t;
name
フィールドに属性の名前が保管されます。
2 文字から
CFG_ATTR_NAME_SZ
定数に保管されている値まで長さの英文字を選択します。
CFG_ATTR_NAME_SZ
定数は,/sys/include/sys/sysconfig.h
ファイルで定義されます。
[例に戻る]
このフィールドに,表 C-1
に示すいずれか 1 つの属性データ型を指定します。
表 C-1: 属性データ型
データ型名 | 説明 |
CFG_ATTR_STRTYPE |
ヌルで終わる文字の配列 (char* ) |
CFG_ATTR_INTTYPE |
32 ビットの符号付きの数値 (int ) |
CFG_ATTR_UINTTYPE |
32 ビットの符号なしの数値 (unsigned ) |
CFG_ATTR_LONGTYPE |
64 ビットの符号付きの数値 (long ) |
CFG_ATTR_ULONGTYPE |
64 ビットの符号なしの数値 |
CFG_ATTR_BINTYPE |
バイトの配列 |
operation
フィールドには,その属性に対して実行できる要求を指定します。
表 C-2
に示す要求コードから 1 つあるいは複数を指定します。
単一の属性の構成除外はできないため,CFG_OP_UNCONFIGURE
要求コードは,個々の属性に対しては意味を持ちません。
したがって,operation
フィールドに
CFG_OP_UNCONFIGURE
は指定できません。
表 C-2: 属性に対して許可される要求を指定するコード
要求コード | 意味 |
CFG_OP_CONFIGURE |
サブシステムが最初に構成されるときに属性の値を設定できる。 |
CFG_OP_QUERY |
サブシステムが構成されていれば,いつでも属性の値を表示できる。 |
CFG_OP_RECONFIGURE |
サブシステムが構成されていれば,いつでも属性の値を変更できる。 |
address
フィールドは,カーネルが属性の値にアクセスするかどうかを決定します。
このフィールドにアドレスを指定すると,カーネルは属性値の読み取りおよび変更を行うことができます。
sysconfig
コマンドからカーネルが照会要求を受信すると,カーネルはこのフィールドに指定されている位置から値を読み取り,その値を返します。
構成要求あるいは再構成要求に対して,カーネルは次の条件をチェックします。
新しい値のデータ型がその属性に対して適切であるか。
その値が属性の最小値と最大値の範囲内であるか。
その値がこれらの条件に当てはまる場合,カーネルは新しい値を属性値として保管します (最大値と最小値は属性定義の次の 2 つのフィールドで指定します)。
サブシステム・コードの属性に対する照会,構成,再構成などの要求に対してユーザが応答することもできます。
この場合,このフィールドに
NULL
を指定します。
属性値の制御方法についての詳細は,C.3 節を参照してください。
[例に戻る]
min
および
max
フィールドは,属性値の最小値と最大値を定義します。
カーネルは,これらの 2 つのフィールドを属性のデータ型に従って別々に解釈します。
属性のデータ型が整数型である場合,これらのフィールドには最小値および最大値を示す整数値が含まれます。
属性のデータ型が
CFG_ATTR_STRTYPE
である場合,これらのフィールドには文字列の最小長および最大長が含まれます。
属性のデータ型が
CFG_ATTR_BINTYPE
である場合は,これらのフィールドには,ユーザが修正することのできる最小バイト数および最大バイト数が含まれます。
[例に戻る]
カーネルがバイナリ属性の内容を読み取ったり変更したりできるように設定するには,binlength
フィールドを使用してそのバイナリ・データの現在の値を指定します。
その属性の保管されているバイナリ・データの長さをカーネルが変更すると,カーネルはこのフィールドの内容も修正します。
属性のデータ型が整数あるいは文字列であるか,バイナリ属性に対する照会要求および再構成要求に対して構成ルーチンで応答したい場合には,このフィールドは使用しません。 [例に戻る]
例 C-1
に示すのは,定義属性テーブルの例です。
この属性テーブルは,架空のカーネル・サブシステム
table_mgr
のものです。
この架空のサブシステムの構成ルーチンについては,C.3 節で説明しています。
例 C-1: 定義属性テーブルの例
#include <sys/sysconfig.h> #include <sys/errno.h> /* * Initialize attributes */ static char name[] = "Default Table"; static int size = 0; static long *table = NULL; /* * Declare attributes in an attribute table */ cfg_subsys_attr_t table_mgr_attrbutes[] = { /* * "name" is the name of the table */ {"name", [1] CFG_ATTR_STRTYPE, [2] CFG_OP_CONFIGURE | CFG_OP_QUERY | CFG_OP_RECONFIGURE, [3] (caddr_t) name, [4] 2, sizeof(name), [5] 0 [6] }, /* * "size" indicates how large the table should be */ {"size", CFG_ATTR_INTTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY | CFG_OP_RECONFIGURE, NULL, 1, 10, 0}, /* * "table" is a binary representation of the table */ {"table", CFG_ATTR_BINTYPE, CFG_OP_QUERY, NULL, 0, 0, 0}, /* * "element" is a cell in the table array */ {"element", CFG_ATTR_LONGTYPE, CFG_OP_QUERY | CFG_OP_RECONFIGURE, NULL, 0, 99, 0}, {,0,0,0,0,0,0} /* required last element */ };
このテーブルの最後のエントリ
{,0,0,0,0,0,0}
は空の属性です。
この属性は属性テーブルの終わりを示すもので,すべての属性テーブルで必要なものです。
この属性テーブルの最初の行は,テーブルの名前を定義しています。
この属性テーブルの名前は
table_mgr_attributes
です。
name
属性のフィールドについて以下に説明します。
属性名は
name
フィールドに保管されます。
name
は,属性テーブルの最初にあるデータ宣言によって "Default Table
" に初期化されています。
[例に戻る]
属性データ型は
CFG_ATTR_STRTYPE
です。
これはヌルで終了する文字列配列です。
[例に戻る]
このフィールドは,対象となる属性に対して実行できる操作を指定します。 この例の場合,この属性に対して構成,照会,再構成が可能です。 [例に戻る]
このフィールドは,カーネルがユーザの属性値にアクセスできるかどうかを決定します。
この例のように,このフィールドにアドレスを指定した場合,カーネルはユーザの属性値の読み取りおよび変更を行うことが可能です。
カーネルが
sysconfig
コマンドから照会要求を受け取った場合,このフィールドに指定した場所の値を読み取り,その値を返します。
構成要求および再構成要求に対しては,カーネルは,新しい値のデータ型がその属性に対して適当かどうかを確認しその値が属性の最小値と最大値の範囲内に収まるかどうかをチェックします。
この値がこれらの要件に該当する場合,カーネルはその属性に対する新しい値を保管します (最小値および最大値は,属性定義の次の 2 つのフィールドで指定します)。
[例に戻る]
これらの 2 つのフィールドは,属性に対する最小値 (この例の場合 2) および最大値 (この例の場合
sizeof(name)
) を定義します。
属性の最小値および最大値として,システムで定義されている値を使用したい場合は,/usr/include/limits.h
ファイルで定義されている定数の 1 つを使用することができます。
[例に戻る]
バイナリ属性の内容をカーネルが読み取り/変更できるように設定するには,このフィールドを使用してバイナリ・データの現在のサイズを指定します。 この属性に保管されているバイナリ・データの長さをカーネルが変更すると,このフィールドの内容も変更されます。
属性が整数または文字列であるか,バイナリ属性に対する照会あるいは再構成要求に構成ルーチンで応答する場合には,このフィールドは使用されません。 [例に戻る]
/sys/include/sys/sysconfig.h
ファイルで定義される通信属性テーブルは,cfg_attr_t
データ型を持ちます。
例 C-2
で示すように,このデータ型は属性の構造体になっています。
例 C-2: 通信属性テーブル
typedef struct cfg_attr { char name[CFG_ATTR_NAME_SZ]; [1] uint type; [2] uint status; [3] uint operation; [4] long index; [5] union { [6] struct { caddr_t val; ulong min_len; ulong max_len; void (*disposal)(); }str; struct { caddr_t val; ulong min_size; ulong max_size; void (*disposal)(); ulong val_size; }bin; struct { caddr_t val; ulong min_len; ulong max_len; }num; }attr; }cfg_attr_t;
name
フィールドには属性の名前を指定します。
属性名の命名規則は,定義属性テーブルの
name
フィールドの命名規則と同じです。
[例に戻る]
status
フィールドには,表 C-3
に示す定義済み状態コードを指定します。
表 C-3: 属性状態コード
状態コード | 意味 |
CFG_ATTR_EEXISTS |
属性が存在しない。 |
CFG_ATTR_EINDEX |
属性インデックスが正しくない。 |
CFG_ATTR_ELARGE |
属性値あるいはサイズが大きすぎる。 |
CFG_ATTR_EMEM |
その属性に対して有効なメモリがない。 |
CFG_ATTR_EOP |
その属性は,要求された操作をサポートしていない。 |
CFG_ATTR_ESMALL |
属性値あるいはサイズが小さすぎる。 |
CFG_ATTR_ESUBSYS |
カーネルによるサブシステムの構成/再構成およびサブシステムに対する照会ヘの応答が許可されない。 サブシステム・コードで応答を行なう必要がある。 |
CFG_ATTR_ETYPE |
属性タイプが正しくない。 あるいは,属性タイプが一致しない。 |
CFG_ATTR_SUCCESS |
操作が正しく行なわれた。 |
index
フィールドには,構造化された属性に対するインデックスを指定します。
[例に戻る]
共用体
attr
には,属性値とその最小値および最大値が含まれます。
CFG_ATTR_STRTYPE
データ型の属性の場合,val
変数には文字列データが含まれます。
最小値および最大値は,文字列長の最小値および最大値となります。
disposal
ルーチンは,アプリケーションによるカーネル・メモリの使用が終ったら,ユーザがカーネル・メモリに自由に書き込むことができるルーチンです。
CFG_ATTR_BINTYPE
データ型の属性の場合,val
フィールドにはバイナリ値が含まれます。
最小値および最大値は,ユーザが変更できるバイト数の最小値および最大値となります。
disposal
ルーチンは,アプリケーションによるカーネル・メモリの使用が終ったら,ユーザがカーネル・メモリに自由に書き込むことができるルーチンです。
val_size
変数にはバイナリ・データの現在のサイズが含まれます。
数値データ型の場合,val
変数には整数値が含まれ,最小値および最大値も整数値となります。
[例に戻る]
この項では,通信属性テーブルの例を示します。
この属性テーブルは,架空のカーネル・サブシステム
table_mgr
のものです。
この架空のサブシステムの構成ルーチンについては,C.3 節で説明しています。
table_mgr_configure( cfg_op_t op, /*Operation code*/ [1] caddr_t indata, /*Data passed to the subsystem*/ [2] ulong indata_size, /*Size of indata*/ caddr_t outdata, /*Data returned to kernel*/ [3] ulong outdata_size) /*Count of return data items*/ {
次の示すのは,table_mgr_configure
通信属性テーブルのフィールドの説明です。
op
変数には,次のいずれかが含まれます。
CFG_OP_CONFIGURE
CFG_OP_QUERY
CFG_OP_RECONFIGURE
CFG_OP_UNCONFIGURE
indata
構造体は,構成ルーチンに対して
indata_size
のデータを提供します。
オペレーション・コードが
CFG_OP_CONFIGURE
あるいは
CFG_OP_QUERY
の場合,このデータは,構成あるいは照会される属性名のリストです。
オペレーション・コードが
CFG_OP_RECONFIGURE
の場合,データは属性名と値で構成されます。
オペレーション・コードが
CFG_OP_UNCONFIGURE
の場合には,構成ルーチンに値は渡されません。
[例に戻る]
outdata
構造体および
outdata_size
変数は,構成サブシステムの将来の拡張機能のためのプレースホルダです。
[例に戻る]
サブシステムを構成可能にするためには,構成ルーチンを定義する必要があります。 このルーチンは定義属性テーブルとともに機能し,サブシステムの構成/再構成,サブシステムの照会に対する応答,サブシステムの構成除外を行ないます。
サブシステムでの必要性に依存して,構成ルーチンは単純であったり複雑であったりします。 構成ルーチンの目的は,カーネルが実行できないタスクを実行することです。 定義属性テーブルによって属性のロケーションをカーネルに知らせることができるので,カーネルは属性に関するすべての構成要求,再構成要求,照会要求を処理することができます。 ただし,これらの要求が発生している間,カーネルにおける処理量は制限されます。 たとえば,カーネルによる属性値の計算などは行えないので,属性値を計算する必要があるような属性については構成ファイルで処理する必要があります。
以降の各項で,構成ルーチンの例を示します。
ここで示すサンプル・ルーチンは,バイナリ・データを保守するための架空のサブシステム
table_mgr
のための構成ルーチンです。
この構成ルーチンは,次のタスクを行います。
最初の構成時に,テーブルに対してカーネル・メモリを割り当てます。
テーブル属性に関する照会を処理します。
システム管理者が要求した際に,テーブルのサイズを変更します。
構成除外の際にカーネル・メモリを解放します。
カーネルに制御を戻します。
このサブシステムのソース・コードは,/usr/examples/cfgmgr
ディレクトリに含まれています。
このサブシステムの定義属性テーブルについてはC.2.2 項を,通信属性テーブルについてはC.2.4 項を参照してください。
C.3.1 初期構成の実行
最初の構成時に,table_mgr
サブシステムは,それが保守するテーブルを作成します。
例 C-1
に示すように,システム管理者は,初期構成時にテーブルの名前とサイズを設定することができます。
これらの値を設定するために,システム管理者は,sysconfigtab
データベースに希望する値を保管しておきます。
サブシステムのコードで定義されているこのテーブルの省略時の名前は,Default Table
です。
また,このテーブルの省略時のサイズはゼロです。
例 C-3
に示すのは,table_mgr
サブシステムの初期構成時に実行されるコードです。
例 C-3: 初期構成の実行
.
.
.
switch(op){ [1] case CFG_OP_CONFIGURE: attributes = (cfg_attr_t*)indata; [2] for (i=0; i<indata_size; i++){ [3] if (attributes[i].status == CFG_ATTR_ESUBSYS) { [4] if (!strcmp("size", attributes[i].name)){ [5] /* Set the size of the table */ table = (long *) kalloc(attributes[i].attr.num.val*sizeof(long)); [6] /* * Make sure that memory is available */ if (table == NULL) { [7] attributes[i].status = CFG_ATTR_EMEM; continue; } /* * Success, so update the new table size and attribute status */ size = attributes[i].attr.num.val; [8] attributes[i].status = CFG_ATTR_SUCCESS; continue; } } } break;
.
.
.
構成ルーチンには
switch
文が含まれます。
この
switch
文によって,サブシステムは多くの操作に対して応答することができます。
サブシステムは
op
変数の値に従って,異なるタスクを実行します。
[例に戻る]
この文は,attributes
ポインタを初期化します。
これにより,indata
構造体で渡されたデータを構成ルーチンが操作できるようになります。
[例に戻る]
for
ループは,構成ルーチンに渡される各属性の状態を確認します。
[例に戻る]
属性の状態フィールドに
CFG_ATTR_ESUBSYS
が含まれている場合,構成ルーチンはその属性を構成しなければなりません。
[例に戻る]
最初の構成時に操作する必要のある唯一の属性は
size
です。
size
属性が現在の属性である場合のみ,if
文内のコードが実行されます。
[例に戻る]
状態フィールドに
CFG_ATTR_ESUBSYS
が含まれ,属性名フィールドに
size
が含まれる場合,ローカル変数
table
はカーネル・メモリ領域のアドレスを受け取ります。
カーネル・メモリ領域は,attributes[i].attr.num.val
で指定されているテーブルのサイズを保管するのに十分な大きさでなければなりません。
attributes[i].attr.num.val
に指定される値は,テーブル内のロングワード数を指定する整数です。
カーネルは
sysconfigtab
データベースから整数値を読み取り,attr
共用体で構成ルーチンに渡します。
[例に戻る]
カーネル・メモリを割り当てることができない場合,kalloc
ルーチンは
NULL
を返します。
テーブルに対してメモリが割り当てられていない場合,構成ルーチンは,メモリを使用できないことを示す
CFG_ATTR_EMEM
を返します。
この場合,カーネルはエラー・メッセージを表示します。
サブシステムはカーネルに構成されますが,システム管理者は,sysconfig
コマンドを使用してテーブルのサイズを再設定する必要があります。
[例に戻る]
カーネル・メモリが正しく割り当てられると,sysconfigtab
ファイルのテーブル・サイズが静的な外部変数
size
に保管されます。
これによりサブシステムは,テーブルのサイズを必要とする操作に対してこの値を使用することができるようになります。
[例に戻る]
table_mgr
サブシステムのユーザは,照会要求によって次の項目を表示するよう要求できます。
テーブルの名前
テーブルのサイズ
テーブルそのもの
テーブルの要素の 1 つ
例 C-1
に示すように,name
属性の宣言には,カーネルがそのテーブルの名前に直接アクセスできるようにアドレス
(caddr_t) name
が含まれています。
このため,構成ルーチンには,テーブル名に関する照会に応答するためのコードは不要です。
例 C-4
に示すのは,照会要求の一部として実行されるコードの例です。
例 C-4: 照会要求に対する応答
switch (op):
.
.
.
case CFG_OP_QUERY: /* * indata is a list of attributes to be queried, and * indata_size is the count of attributes */ attributes = (cfg_attr_t *) indata; [1] for (i = 0; i < indata_size; i++) { [2] if (attributes[i].status == CFG_ATTR_ESUBSYS) { [3] /* * We need to handle the query for the following * attributes. */ if (!strcmp(attributes[i].name, "size")) { [4] /* * Fetch the size of the table. */ attributes[i].attr.num.val = (long) size; attributes[i].status = CFG_ATTR_SUCCESS; continue; } if (!strcmp(attributes[i].name, "table")) { [5] /* * Fetch the address of the table, along with its size. */ attributes[i].attr.bin.val = (caddr_t) table; attributes[i].attr.bin.val_size = size * sizeof(long); attributes[i].status = CFG_ATTR_SUCCESS; continue; } if (!strcmp(attributes[i].name, "element")) { [6] /* * Make sure that the index is in the right range. */ if (attributes[i].index < 1 || attributes[i].index > size) { attributes[i].status = CFG_ATTR_EINDEX; continue; } /* * Fetch the element. */ attributes[i].attr.num.val = table[attributes[i].index - 1]; attributes[i].status = CFG_ATTR_SUCCESS; continue; } } } break;
.
.
.
この文は,attributes
ポインタを初期化します。
これにより,indata
構造体で渡されたデータを構成ルーチンが操作できるようになります。
[例に戻る]
for
ループは,構成ルーチンに渡される各属性の状態を確認します。
[例に戻る]
属性の状態フィールドに
CFG_ATTR_ESUBSYS
が含まれている場合,構成ルーチンはその属性に関する照会に応答しなければなりません。
[例に戻る]
現在の属性が
size
の場合,このルーチンは
size
変数の値を
attr
共用体の
val
フィールド (attributes[i].attr.num.val
) にコピーします。
size
変数の値は整数なので,共用体の
num
の部分が使用されます。
次にこのルーチンは,状態フィールド
attributes[i].status
に
CFG_ATTR_SUCCESS
を保管します。
[例に戻る]
現在の属性が
table
の場合,このルーチンは テーブルのアドレスを
attr
共用体の
val
フィールドに保管します。
この属性はバイナリなので,共用体の
bin
の部分が使用され,テーブルのサイズは
val_size
フィールドに保管されます。
テーブルのサイズは,現在のテーブル・サイズ
size
と,このサイズのロングワードを乗算することにより計算されます。
status
フィールドは
CFG_ATTR_SUCCESS
に設定されて,処理が成功したことを示します。
[例に戻る]
現在の属性が
element
の場合,このルーチンはテーブルの要素の値を
attr
共用体の
val
フィールドに保管します。
各フィールドはロングワードなので,attr
共用体の
num
の部分が使用されます。
sysconfig
コマンド行で指定したインデックスが範囲外の場合,ルーチンは
CFG_ATTR_EINDEX
を状態フィールドに保管します。
この場合,カーネルはエラー・メッセージを表示します。
システム管理者は別のインデックスで再処理する必要があります。
インデックスが範囲内の場合,status
フィールドには
CFG_ATTR_SUCCESS
が設定されて,処理が成功したことを示します。
[例に戻る]
再構成要求は,table_mgr
サブシステムの属性を変更します。
例 C-1
に示す定義属性テーブルでは,次の
table_mgr
属性をシステム管理者が再構成することができます。
テーブルの名前
テーブルのサイズ
テーブルの要素の内容
例 C-1
に示すように,name
属性宣言には,カーネルがテーブル名に直接アクセスできるようにアドレス ((caddr_t) name
) が含まれます。
このため構成ルーチンには,テーブル名の再構成要求に応答するためのコードは不要です。
例 C-5
に示すのは,再構成要求の際に実行されるコードの例です。
例 C-5: 再構成要求に対する応答
switch(op){
.
.
.
case CFG_OP_RECONFIGURE: /* * The indata parameter is a list of attributes to be * reconfigured, and indata_size is the count of attributes. */ attributes = (cfg_attr_t *) indata; [1] for (i = 0; i < indata_size; i++) { [2] if (attributes[i].status == CFG_ATTR_ESUBSYS) { [3] /* * We need to handle the reconfigure for the following * attributes. */ if (!strcmp(attributes[i].name, "size")) { [4] long *new_table; int new_size; /* * Change the size of the table. */ new_size = (int) attributes[i].attr.num.val; [5] new_table = (long *) kalloc(new_size * sizeof(long)); /* * Make sure that we were able to allocate memory. */ if (new_table == NULL) { [6] attributes[i].status = CFG_ATTR_EMEM; continue; } /* * Update the new table with the contents of the old one, * then free the memory for the old table. */ if (size) { [7] bcopy(table, new_table, sizeof(long) * ((size < new_size) ? size : new_size)); kfree(table); } /* * Success, so update the new table address and size. */ table = new_table; [8] size = new_size; attributes[i].status = CFG_ATTR_SUCCESS; continue; } if (!strcmp(attributes[i].name, "element")) { [9] /* * Make sure that the index is in the right range. */ if (attributes[i].index < 1 || attributes[i].index > size) {[10] attributes[i].status = CFG_ATTR_EINDEX; continue; } /* * Update the element. */ table[attributes[i].index - 1] = attributes[i].attr.num.val; [11] attributes[i].status = CFG_ATTR_SUCCESS; continue; } } } break;
.
.
.
この文は,attributes
ポインタを初期化します。
これにより,indata
構造体で渡されたデータを構成ルーチンが操作できるようになります。
[例に戻る]
for
ループは,構成ルーチンに渡される各属性の状態を確認します。
[例に戻る]
属性の状態フィールドに
CFG_ATTR_ESUBSYS
が含まれている場合,構成ルーチンはその属性を再構成しなければなりません。
[例に戻る]
現在の属性が
size
の場合,再構成を行なうとテーブルのサイズが変更されます。
サブシステムは,カーネル・メモリを使用することができ,既存のテーブルのデータを損失しないことを保証する必要があるため,2 つの変数が新たに宣言されます。
new_table
および
new_size
変数は,新しいテーブルの定義と新しいテーブル・サイズを保管します。
[例に戻る]
new_size
変数は,attributes[i].attr.num.val
フィールドで渡される新しいサイズを受け取ります。
この値は
sysconfig
コマンド行で指定されます。
new_table
変数は,新しいテーブル・サイズとして適切なバイト数を含んでいるメモリ領域をポイントするアドレスを受け取ります。
新しいテーブル・サイズは,new_size
変数の値とバイト数のロングワード (sizeof(long)
) の乗算で計算されます。
[例に戻る]
カーネル・メモリを割り当てることができない場合,kalloc
ルーチンは
NULL
を返します。
テーブルに対してメモリが割り当てられていない場合,構成ルーチンは,メモリを使用できないことを示す
CFG_ATTR_EMEM
を返します。
この場合,カーネルはエラー・メッセージを表示します。
システム管理者は,適切な値を指定して
sysconfig
コマンドを再入力する必要があります。
[例に戻る]
この
if
文は,テーブルが存在するかどうかを判断します。
テーブルが存在する場合,サブシステムは既存テーブルから新しいテーブルへデータをコピーし,既存テーブルが占有していたメモリを解放します。
[例に戻る]
最後に,カーネル・メモリが割り当てられ,既存テーブルのデータが保管されたことをサブシステムが確認した後,サブシステムは
new_table
に保管されているアドレスを
table
に移します。
また,サブシステムは新しいテーブル・サイズを
new_size
から
size
へ移します。
CFG_ATTR_SUCCESS
が
status
フィールドに設定されて,操作が正しく行われたことを示します。
[例に戻る]
現在の属性が
element
の場合,サブシステムは新しいテーブル要素をテーブルに保管します。
[例に戻る]
値を保管する前に,指定されたインデックスが有効な範囲内にあるかどうかをルーチンが確認します。
インデックスが範囲外の場合,ルーチンは状態フィールドに
CFG_ATTR_EINDEX
を保管します。
この場合,カーネルはエラー・メッセージを表示します。
システム管理者は,別のインデックスで再操作する必要があります。
[例に戻る]
インデックスが範囲内の場合,サブシステムは,attr
共用体の
val
フィールドをテーブルの要素に保管します。
各要素はロングワードなので,attr
共用体の
num
の部分が使用されます。
操作が正しく行われたことを示す
CFG_ATTR_SUCCESS
が
status
フィールドに設定されます。
[例に戻る]
table_mgr
サブシステムは,テーブル内のすべてのフィールドの値を 2 倍にするアプリケーション固有の演算を定義します。
サブシステムで独自の演算を定義する場合,<sys/sysconfig.h>
ファイルで定義しているように,演算コードは
CFG_OP_SUBSYS_MIN
から
CFG_OP_SUBSYS_MAX
までの範囲でなければなりません。
カーネルは,この範囲の演算コードを受け取ると,直ちにサブシステム・コードに制御を移します。
サブシステム定義の演算に対しては,カーネルは動作しません。
サブシステムに制御が移ると,サブシステムは,要求で渡されたデータの操作を含め,演算を実行します。
次の例は,CFG_OP_SUBSYS_MIN
値を持つ要求に対する応答で実行されたコードです。
switch (op) {
.
.
.
case CFG_OP_SUBSYS_MIN: /* * Double each element of the table. */ for (i=0; ((table != NULL) && (i < size)); i++) table[i] *= 2; break;
.
.
.
}
このコードは,テーブル内の各要素の値を 2 倍にします。
C.3.5 サブシステムの構成除外
table_mgr
サブシステムを構成除外すると,カーネル・メモリが解放されます。
次に示すのは,構成除外要求に応答する際に実行されるコード例です。
switch(op){
.
.
.
case CFG_OP_UNCONFIGURE: /* * Free up the table if we allocated one. */ if (size) kfree(table, size*sizeof(long)); size = 0; break; } return ESUCCESS; }
この構成ルーチンのコードは,テーブルに対してメモリが割り当てられているかどうかを判断します。
メモリが割り当てられている場合,ルーチンは
kfree
関数を使用してメモリを解放します。
C.3.6 構成ルーチンの終了
次に示すのは,return
文の例です。
switch(op){
.
.
.
size = 0; break; } return ESUCCESS;
構成要求,再構成要求,照会要求,あるいは構成除外要求が完了すると,サブシステム構成ルーチンは
ESUCCESS
を返します。
このサブシステムが設計された方法では,構成,照会,再構成,あるいは構成除外要求の全体が失敗することはありません。
C.3.1 項およびC.3.3 項に示すように,個々の属性についての操作が失敗することはあります。
たとえば,1 つ以上のキー属性の構成に失敗したときにサブシステムの構成全体を失敗させたいときのように,状況によっては,サブシステムの構成,再構成,あるいは構成除外を失敗させたい場合があるかもしれません。 次の例は,エラー値でルーチンを終了する例を示しています。
switch(op){
.
.
.
if (table == NULL) { attributes[i].status = CFG_ATTR_EMEM; return ENOMEM; /*Return message from errno.h*/ }
この例の
if
文は,テーブルに対してメモリが割り当てられているかどうかをテストします。
メモリが割り当てられていない場合,サブシステムはエラー状態を返しサブシステムの構成は失敗します。
/sys/include/sys/sysconfig.h
および
/usr/include/errno.h
ファイルで定義されているように,次のメッセージが表示されます。
No memory available for the attribute Not enough core
この場合,システム管理者は,再度
sysconfig
コマンドを実行してサブシステムの構成を行う必要があります。
0 以外の戻り値は,エラー状態と解釈されます。 サブシステムがエラー状態を返した場合は,次のような状況が発生します。
最初の構成でエラーが返されると,サブシステムはカーネルに構成されません。
照会要求でエラーが発生した場合,データの表示は行われません。
構成除外要求でエラーが発生した場合,サブシステムはカーネルから除外されません。
ロード可能なサブシステムを作成する場合,オペレーティング・システムのバージョン番号を確認するためのコードをサブシステムに追加すべきです。 このコードにより,作成したサブシステムとは互換性のないバージョンのオペレーティング・システムにそのサブシステムがロードされるのを防ぎます。
新たにリリースされたオペレーティング・システムが前のバージョンと比較して大きな違いがある場合,このリリースをメジャー・リリースと呼びます。 メジャー・リリースの場合,オペレーティング・システムに対して行われた変更が原因でサブシステムが正しく動作しないことがあるので,オペレーティング・システムのメジャー・リリースごとにテストを行い,必要ならサブシステムを修正する必要があります。 メジャー・リリースでオペレーティング・システムに新たに追加された機能を使用したい場合も同様です。
新たにリリースされたオペレーティング・システムが,前のバージョンと比較して大きな違いがない場合,このリリースをマイナー・リリースと呼びます。 一般に,メジャー・リリースのオペレーティング・システム上では,サブシステムに何も変更を加えないで実行できるはずです。 ただし,新しいオペレーティング・システムでのテストは行うべきです。 オペレーティング・システムに新たに追加された機能を使用したい場合も同様です。
オペレーティング・システムのバージョン番号を調べたい場合は,Tru64 UNIX システムが提供するグローバル・カーネル変数
version_major
および
version_minor
を使用します。
次に示すのは,オペレーティング・システムのバージョンを調べるためのコード例です。
.
.
.
extern int version_major; extern int version_minor; if (version_major != 5 && version_minor != 0) return EVERSION;
この例では,バージョン 5.0 のオペレーティング・システムでサブシステムを実行するように指定しています。
C.5 ロード可能なサブシステムの構築とロード
ロード可能なサブシステムを作成した後,テストのため,それを構築して,カーネルに組み込む必要があります。 この節では,ロード可能なサブシステムの構築およびロード方法について説明します。 実行時の属性構成が可能なスタティック・サブシステムの構築方法については,C.6 節を参照してください。
動的にロード可能なサブシステムを構築するための,次に示すプロシージャでは,ファイル
table_mgr.c
と
table_data.c
に含まれている
table_mgr
という名前のサブシステムを構築しているものとします。
このサブシステムを構築するには,次の手順に従います。
サブシステムのソース・ファイルを
/usr/sys
領域のディレクトリに移動します。
# mkdir /usr/sys/mysubsys # cp table_mgr.c /usr/sys/mysubsys/table_mgr.c # cp table_data.c /usr/sys/mysubsys/table_data.c
ディレクトリ名
mysubsys
は,好みのディレクトリ名に置き換えることができます。
好みのテキスト・エディタを使用して,/usr/sys/conf/files
ファイルを編集し,次の行を挿入します。
# # table_mgr subsystem # MODULE/DYNAMIC/table_mgr optional table_mgr Binary mysubsys/table_mgr.c module table_mgr mysubsys/table_data.c module table_mgr
files
ファイルのエントリは,config
プログラムに対するサブシステムを記述します。
このエントリの最初の行には,次の情報が入っています。
MODULE/DYNAMIC/table_mgr
トークンは,サブシステムが
table_mgr
という名前の動的カーネル・モジュール (オブジェクト・グループ) であることを示します。
optional
キーワードは,サブシステムをカーネルに組み込む必要がないことを示します。
table_mgr
識別子は,sysconfig
および
autosysconfig
コマンド行のサブシステムを識別するトークンです。
この名前を選択する際には,他のサブシステム名に関して,確実に一意であるように十分に注意してください。
サブシステムに対して複数の名前をリストすることができます。
Binary
キーワードは,サブシステムがすでにコンパイルされ,オブジェクト・ファイルがターゲット・カーネル内にリンクできることを示します。
files
ファイル・エントリに続く行には,各モジュールを構成するソース・ファイルへのパス名を指定します。
次のコマンドを入力して,makefile と関連するヘッダ・ファイルを生成します。
# /usr/sys/conf/sourceconfig BINARY
/usr/sys/BINARY
ディレクトリに変更して,次のようにモジュールを構築します。
# cd /usr/sys/BINARY # make table_mgr.mod
エラーなしでモジュールが構築できると,それを
/subsys
ディレクトリに移動して,システムがロードできるようにします。
# cp table_mgr.mod /subsys/
/sbin/sysconfig
コマンドまたは
/sbin/init.d/autosysconfig
コマンドを使用して,サブシステムをロードします。
次に示すコマンド行は,table_mgr
サブシステムのロードおよび構成に使用できます。
# /sbin/sysconfig -c table_mgr
システムをリブートするたびに,そのサブシステムをカーネルに組み込みたい場合は,次のコマンドを入力します。
# /sbin/init.d/autosysconfig add table_mgr
autosysconfig
コマンドは,table_mgr
サブシステムを自動的にカーネルに組み込むサブシステムのリストに追加します。
実行時に属性構成が可能なスタティック・サブシステムを作成すると,テストのため,それをカーネルに組み込む必要があります。 この節では,属性の動的構成をサポートするスタティック・サブシステムの構築方法について説明します。
動的にロード可能なサブシステムを構築するための,次に示すプロシージャでは,ファイル
table_mgr.c
に格納されている
table_mgr
という名前のサブシステムを構築しているものとします。
サブシステムのソース・ファイルを
/usr/sys
領域のディレクトリに移動します。
# mkdir /usr/sys/mysubsys # cp table_mgr.c /usr/sys/mysubsys/table_mgr.c # cp table_data.c /usr/sys/mysubsys/table_data.c
ディレクトリ名
mysubsys
は,好みのディレクトリ名に置き換えることができます。
好みのテキスト・エディタを使用して,/usr/sys/conf/files
ファイルを編集し,次の行を挿入します。
# # table_mgr subsystem # MODULE/STATIC/table_mgr optional table_mgr Binary mysubsys/table_mgr.c module table_mgr mysubsys/table_data.c module table_mgr
files
ファイルのエントリは,config
プログラムに対するサブシステムを記述します。
このエントリの最初の行には,次の情報が入っています。
MODULE/STATIC/table_mgr
トークンは,サブシステムが
table_mgr
という名前の静的カーネル・モジュール (オブジェクト・グループ) であることを示します。
optional
キーワードは,サブシステムをカーネルに組み込む必要がないことを示します。
table_mgr
識別子は,システム構成ファイルのサブシステムを識別するトークンです。
この名前を選択する際には,他のサブシステム名に関して,確実に一意であるように十分に注意してください。
サブシステムに対して複数の名前をリストすることができます。
Binary
キーワードは,サブシステムがすでにコンパイルされ,オブジェクト・ファイルがターゲット・カーネル内にリンクできることを示します。
files
ファイル・エントリに続く行には,各モジュールを構成するソース・ファイルへのパス名を指定します。
/usr/sbin/doconfig
プログラムを実行して,カーネルを再構築します。
# /usr/sbin/doconfig
次のプロンプトに対して,構成ファイルの名前を入力します。
*** KERNEL CONFIGURATION AND BUILD PROCEDURE *** Enter a name for the kernel configuration file. [MYSYS]: MYSYS.TEST
カーネル・サブシステムをテストするため,構成ファイルの新しいファイル名を入力します。
たとえば,MYSYS.TEST
と入力します。
doconfig
プログラムで新しい構成ファイル名を指定すると,システム上の既存の構成ファイルは変更されません。
このようにしておくと,後で既存の構成ファイルを使用して,テスト中のサブシステムを除いて,システムを構成することができます。
Kernel Option Selection メニューからオプション 15 を選択します。 オプション 15 は,新しいカーネル・オプションを追加していることを示します。
次のプロンプトに対して応答すると,構成ファイルを編集することを示します。
Do you want to edit the configuration file? (y/n) [n] yes
すると,doconfig
プログラムはエディタを起動します (doconfig
で起動するエディタを制御するには,EDITOR
環境変数を定義します)。
サブシステムの識別子 (この場合には
table_mgr
) を構成ファイルに追加します。
options TABLE_MGR
エディタを終了すると,doconfig
プログラムが新しい構成ファイルと新しいカーネルを構築します。
新しいカーネルをルート (/) ディレクトリにコピーします。
# cp /usr/sys/MYSYS_TEST/vmunix /vmunix
システムをシャットダウンしてリブートします。
# shutdown -r now
注意
optional
キーワードをstandard
に置き換えると,カーネルでそのモジュールが必須であることを指定できます。standard
キーワードを使用すると,システム構成ファイルを編集する手間を省くことができます。 次に示すfiles
ファイル・エントリは,必須カーネル・モジュールのためのものであり,システム構成ファイルに含まれているかどうかに関係なく,カーネルに組み込まれます。# # table_mgr subsystem # MODULE/STATIC/table_mgr standard Binary mysubsys/table_mgr.c module table_mgr mysubsys/table_data.c module table_mgr
前述のようなエントリを
files
ファイルに記述する場合には,MYSYS:
という名前のシステム上で,次のコマンドを入力することにより,サブシステムをカーネルに追加します。# /usr/sbin/doconfig -c MYSYS
このコマンドの
MYSYS
は,使用しているシステム構成ファイル名と置き換えてください。このコマンドを実行すると,テストしているサブシステム,この場合には
table_mgr
サブシステムを加えて,既存のシステム構成ファイルに記述されているvmunix
カーネルを構築します。
サブシステムにおける構成,照会,再構成,構成除外要求のテストは,sysconfig
コマンドを使用して行うことができます。
サブシステムをテストしている場合は,-v
オプションを指定して
sysconfig
コマンドを入力します。
-v
オプションを指定すると,sysconfig
コマンドは通常より多くの情報を表示します。
このコマンドは,cfgmgr
構成管理サーバと
kloadsrv
カーネル・ローディング・ソフトウェアからの情報を
/dev/console
スクリーンに表示します。
kloadsrv
からの情報は,サブシステムのロードが失敗する原因となる未解決シンボルの名前を調べるのに特に便利です。
多くの場合,カーネル・サブシステムのデバッグには,他のカーネル・プログラムをテストするのと同じように
dbx
,kdebug
,および
kdbx
を使用することができます。
dbx -remote
コマンドを使用して
kdebug
デバッガを使用する場合,サブシステムの
.mod
ファイルは,dbx
を実行しているシステムとリモート・テスト・システムで同じ位置になければなりません。
サブシステムのソース・コードは,dbx
を実行しているシステム上の同じ位置になければなりません。
kdebug
デバッガを使用するために必要な設定については,『Kernel Debugging』を参照してください。
dbx
起動時に動的にロード可能なサブシステムがロードされていない場合は,dbx addobj
コマンドを実行することによりデバッガがサブシステムの開始アドレスを決定することができます。
サブシステムの開始アドレスへデバッガがアクセスできない場合は,サブシステムのデータを調べサブシステムのコードにブレークポイントを設定するために,dbx addobj
コマンドを使用することはできません。
次の手順は,dbx
デバッガを起動して,table_mgr.mod
サブシステムを構成し,addobj
コマンドを入力する方法を示しています。
dbx
デバッガを起動します。
# dbx -k /vmunix dbx version 3.11.4 Type 'help' for help. stopped at [thread_block:1542 ,0xfffffc00002f5334] (dbx)
sysconfig
コマンドを入力して,サブシステムの最初の構成を行います。
# sysconfig -c table_mgr
次のように
addobj
コマンドを入力します。
(dbx) addobj /subsys/table_mgr.mod (dbx) p &table_mgr_configure 0xffffffff895aa000
addobj
コマンドにはサブシステムの絶対パス名を指定してください (dbx
セッションを開始する前にサブシステムがロードされている場合は,addobj
コマンドを実行する必要はありません)。
初めて構成するサブシステムのサブシステム・コードにブレークポイントを設定するには,サブシステムのロードの後,カーネルが構成ルーチンを呼び出す前に,addobj
コマンドを入力します。
サブシステムのロードと構成ファイルの呼び出しの間で実行を停止するには,特別なルーチン
subsys_preconfigure
にブレークポイントを設定します。
次の手順は,このブレークポイントの設定方法を示しています。
dbx
デバッガを起動して,subsys_preconfigure
ルーチンにブレークポイントを設定します。
次のように入力してください。
# dbx -remote /vmunix dbx version 3.11.4 Type 'help' for help. stopped at [thread_block:1542 ,0xfffffc00002f5334] (dbx) stop in subsys_preconfigure (dbx) run
sysconfig
コマンドを入力して
table_mgr
サブシステムを初期構成します。
# sysconfig -c table_mgr
addobj
コマンドを入力して,構成ルーチンにブレークポイントを設定します。
[5] stopped at [subsys_preconfigure:1546 ,0xfffffc0000273c58] (dbx) addobj /subsys/table_mgr.mod (dbx) stop in table_mgr_configure [6] stop in table_mgr_configure (dbx) continue [6] stopped at [table_mgr_configure:47 ,0xffffffff895aa028] (dbx)
subsys_preconfigure
ルーチンで実行が停止したら
dbx
スタック・トレース・コマンド
trace
を実行することにより,構成要求がテスト中のサブシステムに対するものであることを確認できます。
次に,サブシステム構成ルーチンにブレークポイントを設定します。