O provedor proc disponibiliza os testes que pertencem às seguintes atividades: criação e finalização de processo, criação e finalização de LWP, execução de novas imagens de programa e envio e tratamento de sinais.
Os testes proc são descritos na Tabela 25–1.
Tabela 25–1 Testes proc|
Teste |
Descrição |
|---|---|
|
create |
Teste que é acionado quando um processo é criado usando fork(2), forkall(2), fork1(2) ou vfork(2). A psinfo_t correspondente ao novo processo filho é apontada por args[0]. Você pode distinguir vfork das outras variantes de fork procurando por PR_VFORKPno membro pr_flag da lwpsinfo_t do segmento de fork. Você pode distinguir fork1 de forkall examinando os membros pr_nlwp de psinfo_t (curpsinfo) do processo pai e psinfo_t (args[0]) do processo filho. Como o teste create só é acionado depois que o processo é criado com êxito, e como a criação de LWP faz parte da criação de um processo, lwp-create será acionado para quaisquer LWPs criados durante a criação do processo antes que o teste create seja acionado no novo processo. |
|
exec |
Teste que é acionado sempre que um processo carregar uma nova imagem do processo com uma variante da chamada do sistema exec(2): exec(2), execle(2), execlp(2), execv(2), execve(2), execvp(2). O teste exec é acionado antes que a imagem do processo seja carregada. As variáveis de processo como execname e curpsinfo, portanto, contêm o estado do processo antes da imagem ser carregada. Algum tempo depois que o teste exec é acionado, o teste exec-failure ou o teste exec-success será, subseqüentemente, acionado no mesmo segmento. O caminho da nova imagem do processo é apontado por args[0]. |
|
exec-failure |
Teste que é acionado quando uma variante exec(2) tiver falhado. O teste exec-failure é acionado somente depois que o teste exec tiver sido acionado no mesmo segmento. O valor de errno(3C) é fornecido em args[0] . |
|
exec-success |
Teste que é acionado quando uma variante exec(2) tiver sido bem-sucedida. Como o teste exec-failure, o teste exec-success é acionado somente depois que o teste exec é acionado no mesmo segmento. No momento em que o teste exec-success é acionado, variáveis de processo como execname e curpsinfo contêm o estado do processo depois que a nova imagem do processo tiver sido carregada. |
|
exit |
Teste que é acionado quando o processo atual está sendo encerrado. A razão do encerramento, que é expressada como um dos códigos SIGCHLD siginfo.h(3HEAD), está contida em args[0]. |
|
fault |
Teste que é acionado quando uma falha de máquina ocorre em um segmento. O código da falha (conforme definido em proc(4)) está em args[0]. A estrutura siginfo correspondente à falha é apontada por args[1]. Somente as falhas que induzem a um sinal podem acionar o teste fault. |
|
lwp-create |
Teste que é acionado quando um LWP é criado, geralmente como resultado de thr_create(3C). A lwpsinfo_t correspondente ao novo segmento é apontada por args[0]. A psinfo_t do processo que contém o segmento é apontada por args[1]. |
|
lwp-start |
Teste que é acionado no contexto de um LWP recém-criado. O teste lwp-start será acionado antes que quaisquer instruções no nível do usuário sejam executadas. Se o LWP for o primeiro LWP no processo, o teste start será acionado, seguido por lwp-start. |
|
lwp-exit |
Teste que é acionado quando um LWP está sendo encerrado, seja devido a um sinal ou a uma chamada explícita para thr_exit(3C). |
|
signal-discard |
Teste que é acionado quando um sinal é enviado para um processo de segmento único, e o sinal é desbloqueado e ignorado pelo processo. Sob essas condições, o sinal é descartado ao ser gerado. A lwpsinfo_t e a psinfo_t do processo e do segmento de destino estão, respectivamente, em args[0] e args[1]. O número do sinal está em args[2] . |
|
signal-send |
Teste que é acionado quando um sinal é enviado para um segmento ou processo. O teste signal-send é acionado no contexto do processo e do segmento de envio. A lwpsinfo_t e a psinfo_t do processo e do segmento de recebimento estão, respectivamente, em args[0] e args[1]. O número do sinal está em args[2] . signal-send é sempre seguida por signal-handle ou signal-clear no processo e no segmento de recebimento. |
|
signal-handle |
Teste que é acionado imediatamente antes de um teste manipular um sinal. O teste signal-handle é acionado no contexto do segmento que irá manipular o sinal. O número do sinal está em args[0] . Um ponteiro para a estrutura siginfo_t que corresponde ao sinal está em args[1]. O valor de args[1] é NULL se não houver nenhuma estrutura siginfo_t ou se o manipulador de sinal não tiver o sinalizador SA_SIGINFO definido. O endereço do manipulador de sinal no processo está em args[2]. |
|
signal-clear |
Teste que é acionado quando um sinal pendente é cancelado porque o segmento de destino estava aguardando pelo sinal em sigwait(2), sigwaitinfo(3RT) ou sigtimedwait(3RT). Sob essas condições, o sinal pendente é cancelado e o número do sinal é retornado ao chamador. O número do sinal está em args[0] . signal-clear é acionado no contexto do segmento que estava aguardando anteriormente. |
|
start |
Teste que é acionado no contexto de um processo recém-criado. O teste start será acionado antes que quaisquer instruções no nível do usuário sejam executadas no processo. |
Os tipos de argumentos dos testes proc são listados na Tabela 25–2. Os argumentos são descritos na Tabela 25–1.
Tabela 25–2 Argumentos do teste proc|
Teste |
args[0] |
args[1] |
args[2] |
|---|---|---|---|
|
create |
psinfo_t * |
— |
— |
|
exec |
char * |
— |
— |
|
exec-failure |
int |
— |
— |
|
exit |
int |
— |
— |
|
fault |
int |
siginfo_t * |
— |
|
lwp-create |
lwpsinfo_t * |
psinfo_t * |
— |
|
lwp-start |
— |
— |
— |
|
lwp-exit |
— |
— |
— |
|
signal-discard |
lwpsinfo_t * |
psinfo_t * |
int |
|
signal-discard |
lwpsinfo_t * |
psinfo_t * |
int |
|
signal-send |
lwpsinfo_t * |
psinfo_t * |
int |
|
signal-handle |
int |
siginfo_t * |
void (*)(void) |
|
signal-clear |
int |
— |
— |
|
start |
— |
— |
— |
Vários testes proc possuem argumentos do tipo lwpsinfo_t, uma estrutura documentada em proc(4). A definição da estrutura lwpsinfo_t conforme disponível para os consumidores do DTrace é a seguinte:
typedef struct lwpsinfo {
int pr_flag; /* flags; see below */
id_t pr_lwpid; /* LWP id */
uintptr_t pr_addr; /* internal address of thread */
uintptr_t pr_wchan; /* wait addr for sleeping thread */
char pr_stype; /* synchronization event type */
char pr_state; /* numeric thread state */
char pr_sname; /* printable character for pr_state */
char pr_nice; /* nice for cpu usage */
short pr_syscall; /* system call number (if in syscall) */
int pr_pri; /* priority, high value = high priority */
char pr_clname[PRCLSZ]; /* scheduling class name */
processorid_t pr_onpro; /* processor which last ran this thread */
processorid_t pr_bindpro; /* processor to which thread is bound */
psetid_t pr_bindpset; /* processor set to which thread is bound */
} lwpsinfo_t;
O campo pr_flag é uma máscara de bits com sinalizadores que descrevem o processo. Esses sinalizadores e seus significados são descritos na Tabela 25–3.
Tabela 25–3 Valores de pr_flag|
PR_ISSYS |
O processo é um processo do sistema. |
|
PR_VFORKP |
O processo é pai de um filho de vfork(2). |
|
PR_FORK |
O processo possui o modo herança-em-bifurcação definido. |
|
PR_RLC |
O processo possui o modo execução-em-último-encerramento definido. |
|
PR_KLC |
O processo possui o modo eliminação-em-último-encerramento definido. |
|
PR_ASYNC |
O processo possui o modo interrupção-assíncrona definido. |
|
PR_MSACCT |
O processo possui a contabilidade de micro-estado ativada. |
|
PR_MSFORK |
A contabilidade do micro-estado do processo é herdada na bifurcação. |
|
PR_BPTADJ |
O processo possui o modo de ajuste de ponto de interrupção definido. |
|
PR_PTRACE |
O processo possui o modo de compatibilidade com ptrace(3C) definido. |
|
PR_STOPPED |
O segmento é um LWP que está interrompido. |
|
PR_ISTOP |
O segmento é um LWP interrompido em um evento de interesse. |
|
PR_DSTOP |
O segmento é um LWP que possui uma diretiva de interrupção em efeito. |
|
PR_STEP |
O segmento é um LWP que possui uma diretiva de etapa única em efeito. |
|
PR_ASLEEP |
O segmento é um LWP em uma espera que pode ser interrompida em uma chamada do sistema. |
|
PR_DETACH |
O segmento é um LWP desanexado. Consulte pthread_create(3C) e pthread_join(3C). |
|
PR_DAEMON |
O segmento é um LWP daemon. Consulte pthread_create(3C). |
|
PR_AGENT |
O segmento é o LWP do agente do processo. |
|
PR_IDLE |
O segmento é o segmento inativo de uma CPU. Segmentos inativos somente são executados em uma CPU quando as filas de execução da CPU estão vazias. |
O campo pr_addr é o endereço de uma estrutura de dados no kernel, privada, que representa o segmento. Embora a estrutura de dados seja privada, o campo pr_addr pode ser usado como um símbolo exclusivo de um segmento enquanto o segmento existir.
O campo pr_wchan é definido quando o segmento está em modo de espera em um objeto de sincronização. O significado do campo pr_wchan é privado para a implementação do kernel, mas o campo pode ser usado como um símbolo exclusivo para o objeto de sincronização.
O campo pr_stype é definido quando o segmento está em modo de espera em um objeto de sincronização. Os possíveis valores do campo pr_stype estão na Tabela 25–4.
Tabela 25–4 Valores de pr_stype|
SOBJ_MUTEX |
Objeto de sincronização do mutex do kernel. Usado para serializar o acesso a regiões de dados compartilhados no kernel. Consulte o Capítulo 18Provedor lockstat e mutex_init(9F) para obter detalhes sobre objetos de sincronização do mutex no kernel. |
|
SOBJ_RWLOCK |
Objeto de sincronização de leitores/gravador do kernel. Usado para sincronizar o acesso aos objetos compartilhados no kernel que pode permitir vários leitores simultâneos ou um único gravador. Consulte o Capítulo 18Provedor lockstat e rwlock(9F) para obter detalhes sobre objetos de sincronização de leitores/gravador no kernel. |
|
SOBJ_CV |
Objeto de sincronização de variável de condição. Uma variável de condição aguarda indefinidamente até que alguma condição torne-se verdadeira. Variáveis de condição geralmente são usadas para sincronizar por razões diferentes do acesso a uma região de dados compartilhados, e são o mecanismo geralmente usado quando um processo realiza uma espera indefinida direcionada pelo programa. Por exemplo, o bloqueio em poll(2), pause(2), wait(3C) e semelhantes. |
|
SOBJ_SEMA |
Objeto de sincronização de semáforo. Um objeto de sincronização de vários objetivos que, assim como os objetos de variável de condição, não controla uma noção de propriedade. Como a propriedade é necessária para implementar a herança de prioridade no kernel do Solaris, a falta de propriedade inerente em objetos de semáforo impede seu uso amplo. Consulte semaphore(9F) para obter detalhes. |
|
SOBJ_USER |
Objeto de sincronização no nível do usuário. Todos os bloqueios em objetos de sincronização no nível do usuário são manipulados com objetos de sincronização SOBJ_USER . Os objetos de sincronização no nível do usuário incluem aqueles criados com mutex_init(3C), sema_init(3C), rwlock_init(3C), cond_init(3C) e seus equivalentes POSIX. |
|
SOBJ_USER_PI |
Objeto de sincronização no nível do usuário que implementa a herança de prioridade. Alguns objetos de sincronização no nível do usuário que controlam a propriedade adicionalmente permitem a herança de prioridade. Por exemplo, objetos do mutex criados com pthread_mutex_init(3C) podem ser feitos para herdar prioridade usando-se pthread_mutexattr_setprotocol(3C). |
|
SOBJ_SHUTTLE |
Objeto de sincronização de deslocamento. Objetos de deslocamento são usados para implementar portas. Consulte door_create(3DOOR) para obter mais informações. |
O campo pr_state é definido como um dos valores na Tabela 25–5. O campo pr_sname é definido como um caractere correspondente mostrado entre parênteses na mesma tabela.
Tabela 25–5 Valores de pr_state|
SSLEEP (S) |
O segmento está em espera. O teste sched:::sleep será acionado imediatamente antes que o estado de um segmento passe para SSLEEP. |
|
SRUN (R) |
O segmento é executável, mas não está sendo executado no momento. O teste sched:::enqueue será acionado imediatamente antes que o estado de um segmento passe para SRUN. |
|
SZOMB (Z) |
O segmento é um LWP zumbi. |
|
SSTOP (T) |
O segmento é interrompido, seja devido a uma diretiva proc(4) explícita ou a algum outro mecanismo de interrupção. |
|
SIDL (I) |
O segmento é um estado intermediário durante a criação do processo. |
|
SONPROC (O) |
O segmento está sendo executado em uma CPU. O teste sched:::on-cpu será acionado no contexto do segmento SONPROC logo depois que o estado do segmento passar para SONPROC. |
Vários testes proc possuem um argumento do tipo psinfo_t, uma estrutura documentada em proc(4). A definição da estrutura de psinfo_t conforme disponível aos consumidores do DTrace é a seguinte:
typedef struct psinfo {
int pr_nlwp; /* number of active lwps in the process */
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 */
gid_t pr_gid; /* real group id */
gid_t pr_egid; /* effective group id */
uintptr_t pr_addr; /* address of process */
dev_t pr_ttydev; /* controlling tty device (or PRNODEV) */
timestruc_t pr_start; /* process start time, from the epoch */
char pr_fname[PRFNSZ]; /* name of execed file */
char pr_psargs[PRARGSZ]; /* initial characters of arg list */
int pr_argc; /* initial argument count */
uintptr_t pr_argv; /* address of initial argument vector */
uintptr_t pr_envp; /* address of initial environment vector */
char pr_dmodel; /* data model of the process */
taskid_t pr_taskid; /* task id */
projid_t pr_projid; /* project id */
poolid_t pr_poolid; /* pool id */
zoneid_t pr_zoneid; /* zone id */
} psinfo_t;
O campo pr_dmodel é definido como PR_MODEL_ILP32 , indicando um processo de 32 bits, ou PR_MODEL_LP64, indicando um processo de 64 bits.
Você pode usar o teste exec para determinar facilmente quais programas estão sendo executados, e por quem, conforme mostrado no seguinte exemplo:
#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", @);
}
A execução do script de exemplo por um curto período de tempo em uma máquina de compilação produz um resultado similar ao seguinte exemplo:
# dtrace -s ./whoexec.d ^C WHO WHAT COUNT make.bin yacc 1 tcsh make 1 make.bin spec2map 1 sh grep 1 lint lint2 1 sh lint 1 sh ln 1 cc ld 1 make.bin cc 1 lint lint1 1 sh lex 1 make.bin mv 2 sh sh 3 sh make 3 sh sed 4 sh tr 4 make make.bin 4 sh install.bin 5 sh rm 6 cc ir2hf 33 cc ube 33 sh date 34 sh mcs 34 cc acomp 34 sh cc 34 sh basename 34 basename expr 34 make.bin sh 87 |
Se você desejar saber o tempo de execução dos programas da criação ao encerramento, poderá ativar os testes start e exit, conforme mostrado no exemplo a seguir:
proc:::start
{
self->start = timestamp;
}
proc:::exit
/self->start/
{
@[execname] = quantize(timestamp - self->start);
self->start = 0;
}
A execução do script de exemplo no servidor de compilação por vários segundos produz um resultado similar ao seguinte exemplo:
# dtrace -s ./progtime.d
dtrace: script './progtime.d' matched 2 probes
^C
ir2hf
value ------------- Distribution ------------- count
4194304 | 0
8388608 |@ 1
16777216 |@@@@@@@@@@@@@@@@ 14
33554432 |@@@@@@@@@@ 9
67108864 |@@@ 3
134217728 |@ 1
268435456 |@@@@ 4
536870912 |@ 1
1073741824 | 0
ube
value ------------- Distribution ------------- count
16777216 | 0
33554432 |@@@@@@@ 6
67108864 |@@@ 3
134217728 |@@ 2
268435456 |@@@@ 4
536870912 |@@@@@@@@@@@@ 10
1073741824 |@@@@@@@ 6
2147483648 |@@ 2
4294967296 | 0
acomp
value ------------- Distribution ------------- count
8388608 | 0
16777216 |@@ 2
33554432 | 0
67108864 |@ 1
134217728 |@@@ 3
268435456 | 0
536870912 |@@@@@ 5
1073741824 |@@@@@@@@@@@@@@@@@@@@@@@@@ 22
2147483648 |@ 1
4294967296 | 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
make.bin
value ------------- Distribution ------------- count
16777216 | 0
33554432 |@ 1
67108864 |@ 1
134217728 |@@ 2
268435456 | 0
536870912 |@@ 2
1073741824 |@@@@@@@@@ 9
2147483648 |@@@@@@@@@@@@@@@ 14
4294967296 |@@@@@@ 6
8589934592 |@@ 2
17179869184 | 0
|
Em vez de saber quanto tempo um processo em particular demora para ser executado, talvez você queira saber quanto tempo segmentos individuais demoram para ser executados. O exemplo a seguir mostra como usar os testes lwp-start e lwp-exit com esta finalidade:
proc:::lwp-start
/tid != 1/
{
self->start = timestamp;
}
proc:::lwp-exit
/self->start/
{
@[execname] = quantize(timestamp - self->start);
self->start = 0;
}
A execução do script de exemplo em um servidor de calendário e NFS produz um resultado similar ao seguinte exemplo:
# dtrace -s ./lwptime.d
dtrace: script './lwptime.d' matched 3 probes
^C
nscd
value ------------- Distribution ------------- count
131072 | 0
262144 |@ 18
524288 |@@ 24
1048576 |@@@@@@@ 75
2097152 |@@@@@@@@@@@@@@@@@@@@@@@ 245
4194304 |@@ 22
8388608 |@@ 24
16777216 | 6
33554432 | 3
67108864 | 1
134217728 | 1
268435456 | 0
mountd
value ------------- Distribution ------------- count
524288 | 0
1048576 |@ 15
2097152 |@ 24
4194304 |@@@ 51
8388608 |@ 17
16777216 |@ 24
33554432 |@ 15
67108864 |@@@@ 57
134217728 |@ 28
268435456 |@ 26
536870912 |@@ 39
1073741824 |@@@ 45
2147483648 |@@@@@ 72
4294967296 |@@@@@ 77
8589934592 |@@@ 55
17179869184 | 14
34359738368 | 2
68719476736 | 0
automountd
value ------------- Distribution ------------- count
1048576 | 0
2097152 | 3
4194304 |@@@@ 146
8388608 | 6
16777216 | 6
33554432 | 9
67108864 |@@@@@ 203
134217728 |@@ 87
268435456 |@@@@@@@@@@@@@@@ 534
536870912 |@@@@@@ 223
1073741824 |@ 45
2147483648 | 20
4294967296 | 26
8589934592 | 20
17179869184 | 19
34359738368 | 7
68719476736 | 2
137438953472 | 0
iCald
value ------------- Distribution ------------- count
8388608 | 0
16777216 |@@@@@@@ 20
33554432 |@@@ 9
67108864 |@@ 8
134217728 |@@@@@ 16
268435456 |@@@@ 11
536870912 |@@@@ 11
1073741824 |@ 4
2147483648 | 2
4294967296 | 0
8589934592 |@@ 8
17179869184 |@ 5
34359738368 |@ 4
68719476736 |@@ 6
137438953472 |@ 4
274877906944 | 2
549755813888 | 0
|
Você pode usar o teste signal-send para determinar o processo de envio e recebimento associado a qualquer sinal, conforme mostrado no exemplo a seguir:
#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", @);
}
Executar este script acima resultará numa saída semelhante ao exemplo seguinte:
# dtrace -s ./sig.d
^C
SENDER RECIPIENT SIG COUNT
xterm dtrace 2 1
xterm soffice.bin 2 1
tr init 18 1
sched test 18 1
sched fvwm2 18 1
bash bash 20 1
sed init 18 2
sched ksh 18 15
sched Xsun 22 471
|
O provedor proc usa o mecanismo de estabilidade do DTrace para descrever suas estabilidades, conforme mostrado na tabela a seguir. Para obter mais informações sobre o mecanismo de estabilidade, consulte o Capítulo 39Estabilidade.
|
Elemento |
Estabilidade de nome |
Estabilidade de dados |
Classe de dependência |
|---|---|---|---|
|
Provedor |
Desenvolvendo |
Desenvolvendo |
ISA |
|
Módulo |
Privada |
Privada |
Desconhecida |
|
Função |
Privada |
Privada |
Desconhecida |
|
Nome |
Desenvolvendo |
Desenvolvendo |
ISA |
|
Argumentos |
Desenvolvendo |
Desenvolvendo |
ISA |