Procプロバイダ
proc
プロバイダは、プロセスの作成と終了、LWPの作成と終了、新しいプログラム・イメージの実行、およびシグナルの送信と処理に関連するプローブを使用可能にします。
procプローブ
次の表に、proc
プロバイダのプローブを示します。
表8-3 procプローブ
プローブ | 説明 |
---|---|
|
|
|
プロセスが |
|
|
|
|
|
現在のプロセスが終了しようとするときに起動します。終了の理由が、いずれかの |
|
プロセス・スレッドの作成時に起動します。後者は通常、 |
|
シグナル、または |
|
新しく作成されたプロセスまたはプロセス・スレッドのコンテキストで起動します。 |
|
ターゲット・スレッドが |
|
シングルスレッド・プロセスにシグナルが送信され、シグナルがプロセスによってブロック解除されて無視されたときに起動します。この条件では、シグナルは作成後すぐに破棄されます。ターゲット・プロセスおよびスレッドの |
|
スレッドがシグナルを処理する直前に起動します。 |
|
プロセス、またはプロセスによって作成されたスレッドにシグナルが送信されたときに起動します。 |
|
新しく作成されたプロセスのコンテキストで起動します。 |
ノート:
Linuxでは、プロセスとプロセスが作成するスレッドの間に基本的な違いはありません。プロセスのスレッドはリソースを共有できるように設定されますが、各スレッドはプロセス表に独自のエントリを持ち、プロセスIDも独自です。
procプローブの引数
次の表は、proc
プローブの引数の型を示しています。引数の詳細は、「procプローブ」を参照してください。
表8-4 procプローブの引数
プローブ | args[0] | args[1] | args[2] |
---|---|---|---|
|
|
— |
— |
|
|
— |
— |
|
|
— |
— |
|
— |
— |
— |
|
|
— |
— |
|
|
|
— |
|
— |
— |
— |
|
— |
— |
— |
|
|
— |
— |
|
|
|
|
|
|
|
|
|
|
|
|
|
— |
— |
— |
lwpsinfo_t
一部のproc
プローブは、lwpsinfo_t
型の引数をとります。このデータ構造体の詳細は、/usr/lib64/dtrace/version/procfs.d
を参照してください。lwpsinfo_t
構造体の定義は、次のとおりです:
typedef struct lwpsinfo {
int pr_flag; /* lwp flags (DEPRECATED) */
int pr_lwpid; /* lwp id */
uintptr_t pr_addr; /* internal address of lwp */
uintptr_t pr_wchan; /* wait addr for sleeping lwp */
char pr_stype; /* sync event type */
char pr_state; /* numeric lwp state */
char pr_sname; /* printable char for pr_state */
char pr_nice; /* nice for cpu usage */
short pr_syscall; /* syscall number */
char pr_oldpri; /* priority */
char pr_cpu; /* CPU usage */
int pr_pri; /* priority */
ushort_t pr_pctcpu; /* % of recent cpu time */
ushort_t pr_pad;
timestruc_t pr_start; /* lwp start time */
timestruc_t pr_time; /* usr+sys cpu time */
char pr_clname[8]; /* scheduling class name */
char pr_name[16]; /* name */
processorid_t pr_onpro; /* processor last ran on */
processorid_t pr_bindpro; /* processor bound to */
psetid_t pr_bindpset; /* processor set */
int pr_lgrp; /* lwp home lgroup */
int pr_filler[4];
} lwpsinfo_t;
ノート:
Linuxには、軽量プロセスは存在しません。かわりに、Oracle Linuxのタスク・リストでは、プロセスとスレッドはstruct task_struct
型のプロセス記述子によって表されます。DTraceは、lwpsinfo_t
のメンバーを、Oracle Linuxプロセスのtask_struct
から変換します。
スレッドが停止する場合、pr_flag
は1
に設定されます。それ以外の場合は、0
に設定されます。
Oracle Linuxでは、pr_stype
フィールドはサポートされていないため、常に0
です。
次の表では、pr_state
が受取り可能な値について、それに対応するpr_sname
の文字値を含めて説明します。
表8-5 pr_stateの値
pr_state Value | pr_sname Value
|
説明 |
---|---|---|
|
R
|
スレッドは実行可能であるか、CPUで実行中です。
Oracle Linuxで同等のタスク状態は、 |
|
S
|
スレッドはスリープ中です。
Oracle Linuxで同等のタスク状態は、 |
|
T
|
スレッドは、明示的な
Oracle Linuxで同等のタスク状態は、 |
|
W
|
スレッドは待機キューで待機中です。
Oracle Linuxで同等のタスク状態は、 |
|
Z
|
スレッドはゾンビです。
Oracle Linuxで同等のタスク状態は、 |
psinfo_t
一部のproc
プローブは、psinfo_t
型の引数をとります。このデータ構造体の詳細は、/usr/lib64/dtrace/version/procfs.d
を参照してください。psinfo_t
構造体の定義は、次のとおりです:
typedef struct psinfo {
int pr_flag; /* process flags (DEPRECATED) */
int pr_nlwp; /* number of active lwps (Linux: 1) */
pid_t pr_pid; /* unique process id */
pid_t pr_ppid; /* process id of parent */
pid_t pr_pgid; /* pid of process group leader */
pid_t pr_sid; /* session id */
uid_t pr_uid; /* real user id */
uid_t pr_euid; /* effective user id */
uid_t pr_gid; /* real group id */
uid_t pr_egid; /* effective group id */
uintptr_t pr_addr; /* address of process */
size_t pr_size; /* size of process image (in KB) */
size_t pr_rssize; /* resident set sie (in KB) */
size_t pr_pad1;
struct tty_struct *pr_ttydev; /* controlling tty (or -1) */
ushort_t pr_pctcpu; /* % of recent cpu time used */
ushort_t pr_pctmem; /* % of recent memory used */
timestruc_t pr_start; /* process start time */
timestruc_t pr_time; /* usr+sys cpu time for process */
timestruc_t pr_ctime; /* usr+sys cpu time for children */
char pr_fname[16]; /* name of exec'd file */
char pr_psargs[80]; /* initial chars of arg list */
int pr_wstat; /* if zombie, wait() status */
int pr_argc; /* initial argument count */
uintptr_t pr_argv; /* address of initial arg vector */
uintptr_t pr_envp; /* address of initial env vector */
char pr_dmodel; /* data model */
char pr_pad2[3];
taskid_t pr_taskid; /* task id */
dprojid_t pr_projid; /* project id */
int pr_nzomb; /* number of zombie lwps (Linux: 0) */
poolid_t pr_poolid; /* pool id */
zoneid_t pr_zoneid; /* zone id */
id_t pr_contract; /* process contract */
int pr_filler[1];
lwpsinfo_t pr_lwp;
} psinfo_t;
ノート:
Linuxには、軽量プロセスは存在しません。Oracle Linuxのタスク・リストでは、プロセスとスレッドはstruct task_struct
型のプロセス記述子によって表されます。DTraceは、psinfo_t
のメンバーを、Oracle Linuxプロセスのtask_struct
から変換します。
pr_dmodel
は、32ビット・プロセスを表すPR_MODEL_ILP32
か、64ビット・プロセスを表すPR_MODEL_LP64
に設定されます。
procの例
次の例は、proc
プロバイダによって公開されるプローブの使用を示しています。
exec、exec-successおよびexec-failure
次の例は、exec
、exec-success
およびexec-failure
のプローブを使用して、どのプログラムがどの親プロセスによって実行されているかを簡単に判断する方法を示しています。次のDソース・コードを入力して、whoexec.d
という名前のファイルに保存します:
#pragma D option quiet
proc:::exec
{
self->parent = execname;
}
proc:::exec-success
/self->parent != NULL/
{
@[self->parent, execname] = count();
self->parent = NULL;
}
proc:::exec-failure
/self->parent != NULL/
{
self->parent = NULL;
}
END
{
printf("%-20s %-20s %s\n", "WHO", "WHAT", "COUNT");
printa("%-20s %-20s %@d\n", @);
}
この例のスクリプトを短時間実行すると、次のような出力が得られます:
WHO WHAT COUNT
bash date 1
bash grep 1
bash ssh 1
bash wc 1
bash ls 2
bash sed 2
...
startプローブとexitプローブ
プログラムが作成されてから終了するまでの実行時間を調べるには、次の例で示すようにstart
プローブとexit
プローブを有効にします。progtime.d
という名前のファイルに保存します。
proc:::start
{
self->start = timestamp;
}
proc:::exit
/self->start/
{
@[execname] = quantize(timestamp - self->start);
self->start = 0;
}
ビルド・サーバー上で数秒間この例のスクリプトを実行すると、次のような出力が得られます。
...
cc
value ------------- Distribution ------------- count
33554432 | 0
67108864 |@@@ 3
134217728 |@ 1
268435456 | 0
536870912 |@@@@ 4
1073741824 |@@@@@@@@@@@@@@ 13
2147483648 |@@@@@@@@@@@@ 11
4294967296 |@@@ 3
8589934592 | 0
sh
value ------------- Distribution ------------- count
262144 | 0
524288 |@ 5
1048576 |@@@@@@@ 29
2097152 | 0
4194304 | 0
8388608 |@@@ 12
16777216 |@@ 9
33554432 |@@ 9
67108864 |@@ 8
134217728 |@ 7
268435456 |@@@@@ 20
536870912 |@@@@@@ 26
1073741824 |@@@ 14
2147483648 |@@ 11
4294967296 | 3
8589934592 | 1
17179869184 | 0
...
signal-send
次の例は、signal-send
プローブを使用して、シグナルに関連付けられたプロセスの送受信を確認する方法を示しています。次のDソース・コードを入力し、sig.d
という名前のファイルに保存します。
#pragma D option quiet
proc:::signal-send
{
@[execname, stringof(args[1]->pr_fname), args[2]] = count();
}
END
{
printf("%20s %20s %12s %s\n",
"SENDER", "RECIPIENT", "SIG", "COUNT");
printa("%20s %20s %12d %@d\n", @);
}
このスクリプトを実行すると、次のような出力が得られます。
SENDER RECIPIENT SIG COUNT
kworker/u16:7 dtrace 2 1
kworker/u16:7 sudo 2 1
swapper/2 sssd_kcm 34 1
swapper/6 pmlogger 14 1