このセクションでは、exacct ファイルにアクセスするためのコード例を示します。
使用例 3 指定された pid の exacct データの表示この例は、特定の pid の exacct データをカーネルのスナップショットで示しています。
... ea_object_t *scratch; int unpk_flag = EUP_ALLOC; /* use the same allocation flag */ /* for unpack and free */ /* Omit return value checking, to keep code samples short */ bsize = getacct(P_PID, pid, NULL, 0); buf = malloc(bsize); /* Retrieve exacct object and unpack */ getacct(P_PID, pid, buf, bsize); ea_unpack_object(&scratch, unpk_flag, buf, bsize); /* Display the exacct record */ disp_obj(scratch); if (scratch->eo_type == EO_GROUP) { disp_group(scratch); } ea_free_object(scratch, unpk_flag); ...使用例 4 カーネルビルド中の個々のタスクの識別
この例では、カーネルビルドを評価し、このタスクによってビルドされるソースツリーの一部を表す文字列を示します。ソースディレクトリごとの分析に役立てるために、ビルドされるソースの一部を示します。
この例について次の重要なポイントに注意してください。
make の時間の集約には多くのプロセスが含まれることがあるため、各 make はタスクとして開始されます。make の子プロセスは別のタスクとして作成されます。makefile ツリー全体で集約するには、タスクの親子関係を識別する必要があります。
タスクの exacct ファイルにこの情報を含むタグを追加します。このタスクの make 操作でビルドされるソースツリーの一部を表す現在の作業ディレクトリの文字列を追加します。
ea_set_item(&cwd, EXT_STRING | EXC_LOCAL | MY_CWD, cwdbuf, strlen(cwdbuf));
... /* Omit return value checking and error processing */ /* to keep code sample short */ ptid = gettaskid(); /* Save "parent" task-id */ tid = settaskid(getprojid(), TASK_NORMAL); /* Create new task */ /* Set data for item objects ptskid and cwd */ ea_set_item(&ptskid, EXT_UINT32 | EXC_LOCAL | MY_PTID, &ptid, 0); ea_set_item(&cwd, EXT_STRING | EXC_LOCAL | MY_CWD, cwdbuf, strlen(cwdbuf)); /* Set grp object and attach ptskid and cwd to grp */ ea_set_group(&grp, EXT_GROUP | EXC_LOCAL | EXD_GROUP_HEADER); ea_attach_to_group(&grp, &ptskid); ea_attach_to_group(&grp, &cwd); /* Pack the object and put it back into the accounting stream */ ea_buflen = ea_pack_object(&grp, ea_buf, sizeof(ea_buf)); putacct(P_TASKID, tid, ea_buf, ea_buflen, EP_EXACCT_OBJECT); /* Memory management: free memory allocate in ea_set_item */ ea_free_item(&cwd, EUP_ALLOC); ...使用例 5 システムの exacct ファイルの内容の読み取りと表示
この例では、プロセスまたはタスク用にシステムの exacct ファイルの読み取りまたは表示を行う方法を示します。
この例について次の重要なポイントに注意してください。
ファイル内の次のオブジェクトを取得するには、ea_get_object() を呼び出します。EOF が exacct ファイルの完全なトラバーサルを有効にするまで ea_get_object() をループで呼び出します。
catalog_name() は、catalog_item 構造体を使用して、Oracle Solaris カタログのタイプ ID をオブジェクトデータの内容を表す意味のある文字列に変換します。タイプ ID は最下位の 24 ビットつまり 3 バイトをマスキングすることで取得されます。
switch(o->eo_catalog & EXT_TYPE_MASK) { case EXT_UINT8: printf(" 8: %u", o->eo_item.ei_uint8); break; case EXT_UINT16: ... }
TYPE_MASK の上位 4 ビットは、データ型を調べてオブジェクトの実際のデータを出力するために使用されます。
disp_group() は、グループオブジェクトへのポインタとグループ内のオブジェクト数を取得します。グループ内の各オブジェクトに対して、disp_group() は disp_obj() を呼び出し、オブジェクトがグループオブジェクトの場合は disp_group() を再帰的に呼び出します。
/* Omit return value checking and error processing */ /* to keep code sample short */ main(int argc, char *argv) { ea_file_t ef; ea_object_t scratch; char *fname; fname = argv[1]; ea_open(&ef, fname, NULL, EO_NO_VALID_HDR, O_RDONLY, 0); bzero(&scratch, sizeof (ea_object_t)); while (ea_get_object(&ef, &scratch) != -1) { disp_obj(&scratch); if (scratch.eo_type == EO_GROUP) disp_group(&ef, scratch.eo_group.eg_nobjs); bzero(&scratch, sizeof (ea_object_t)); } ea_close(&ef); } struct catalog_item { /* convert Oracle Solaris catalog's type ID */ /* to a meaningful string */ int type; char *name; } catalog[] = { { EXD_VERSION, "version\t" }, ... { EXD_PROC_PID, " pid\t" }, ... }; static char * catalog_name(int type) { int i = 0; while (catalog[i].type != EXD_NONE) { if (catalog[i].type == type) return (catalog[i].name); else i++; } return ("unknown\t"); } static void disp_obj(ea_object_t *o) { printf("%s\t", catalog_name(o->eo_catalog & 0xffffff)); switch(o->eo_catalog & EXT_TYPE_MASK) { case EXT_UINT8: printf(" 8: %u", o->eo_item.ei_uint8); break; case EXT_UINT16: ... } static void disp_group(ea_file_t *ef, uint_t nobjs) { for (i = 0; i < nobjs; i++) { ea_get_object(ef, &scratch)); disp_obj(&scratch); if (scratch.eo_type == EO_GROUP) disp_group(ef, scratch.eo_group.eg_nobjs); } }