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 |