O provedor Statically Defined Tracing (SDT) cria testes nos locais que um programador de software designou formalmente. O mecanismo do SDT permite aos programadores escolher conscientemente os locais de interesse para usuários do DTrace e transmitir algum conhecimento semântico sobre cada local através do nome do teste. O kernel do Solaris definiu uma série de testes SDT, e provavelmente adicionará outros mais ao longo do tempo. O DTrace também fornece um mecanismo para desenvolvedores de aplicativos do usuário definirem testes estáticos, descrito no Capítulo 34Rastreio definido estaticamente em aplicativos do usuário.
Os testes do SDT definidos pelo kernel do Solaris estão listados na Tabela 22–1. A estabilidade do nome e a estabilidade dos dados destes testes são ambas Privadas, pois sua descrição aqui reflete a implementação do kernel e não deve ser considerada como um comprometimento de interface. Para obter mais informações sobre o mecanismo de estabilidade do DTrace, consulte Estabilidade.
Tabela 22–1 Testes SDT
Nome do teste |
Descrição |
arg0 |
---|---|---|
callout-start |
Teste que é acionado imediatamente antes da execução de um callout (consulte <sys/callo.h>). Os callouts são executados pelo relógio periódico do sistema e representam a implementação de timeout(9F). |
O ponteiro para callout_t (consulte <sys/callo.h>) correspondente ao callout a ser executado. |
callout-end |
Teste que é acionado imediatamente depois da execução de um callout (consulte <sys/callo.h>). |
O ponteiro para callout_t (consulte <sys/callo.h>) correspondente ao callout que acabou de ser executado. |
interrupt-start |
Teste que é acionado imediatamente antes da chamada do manipulador de interrupção do dispositivo. |
O ponteiro para a estrutura dev_info (consulte <sys/ddi_impldefs.h> ) correspondente ao dispositivo de interrupção. |
interrupt-complete |
Teste que é acionado imediatamente depois do retorno do manipulador de interrupção de um dispositivo. |
O ponteiro para a estrutura dev_info (consulte <sys/ddi_impldefs.h> ) correspondente ao dispositivo de interrupção. |
O exemplo seguinte é um script para observar o comportamento do callout por segundo:
#pragma D option quiet sdt:::callout-start { @callouts[((callout_t *)arg0)->c_func] = count(); } tick-1sec { printa("%40a %10@d\n", @callouts); clear(@callouts); }
Executar este exemplo revela os usuários freqüentes do timeout(9F) no sistema, conforme mostrado na saída seguinte:
# dtrace -s ./callout.d FUNC COUNT TS`ts_update 1 uhci`uhci_cmd_timeout_hdlr 3 genunix`setrun 5 genunix`schedpaging 5 ata`ghd_timeout 10 uhci`uhci_handle_root_hub_status_change 309 FUNC COUNT ip`tcp_time_wait_collector 1 TS`ts_update 1 uhci`uhci_cmd_timeout_hdlr 3 genunix`schedpaging 4 genunix`setrun 8 ata`ghd_timeout 10 uhci`uhci_handle_root_hub_status_change 300 FUNC COUNT ip`tcp_time_wait_collector 0 iprb`mii_portmon 1 TS`ts_update 1 uhci`uhci_cmd_timeout_hdlr 3 genunix`schedpaging 4 genunix`setrun 7 ata`ghd_timeout 10 uhci`uhci_handle_root_hub_status_change 300 |
A interface de timeout(9F) somente produz uma única expiração de temporizador. Os consumidores de timeout() que requerem a funcionalidade de temporizador de intervalo geralmente reinstalam seu timeout a partir do manipulador timeout(). O exemplo seguinte mostra este comportamento:
#pragma D option quiet sdt:::callout-start { self->callout = ((callout_t *)arg0)->c_func; } fbt::timeout:entry /self->callout && arg2 <= 100/ { /* * In this case, we are most interested in interval timeout(9F)s that * are short. We therefore do a linear quantization from 0 ticks to * 100 ticks. The system clock's frequency — set by the variable * "hz" — defaults to 100, so 100 system clock ticks is one second. */ @callout[self->callout] = lquantize(arg2, 0, 100); } sdt:::callout-end { self->callout = NULL; } END { printa("%a\n%@d\n\n", @callout); }
Executar este script e esperar alguns segundos antes de digitar Control-C resulta em uma saída semelhante ao exemplo seguinte:
# dtrace -s ./interval.d ^C genunix`schedpaging value ------------- Distribution ------------- count 24 | 0 25 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 20 26 | 0 ata`ghd_timeout value ------------- Distribution ------------- count 9 | 0 10 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 51 11 | 0 uhci`uhci_handle_root_hub_status_change value ------------- Distribution ------------- count 0 | 0 1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1515 2 | 0 |
A saída mostra que a uhci_handle_root_hub_status_change() no driver uhci(7D) representa o temporizador de intervalo mais curto no sistema: ele é chamado a cada tique-taque do relógio do sistema.
O teste interrupt-start pode ser usado para entender a atividade de interrupção. O exemplo seguinte mostra como quantizar o tempo gasto ao executar um manipulador de interrupção pelo nome do driver:
interrupt-start { self->ts = vtimestamp; } interrupt-complete /self->ts/ { this->devi = (struct dev_info *)arg0; @[stringof(`devnamesp[this->devi->devi_major].dn_name), this->devi->devi_instance] = quantize(vtimestamp - self->ts); }
Executar este script acima resultará numa saída semelhante ao exemplo seguinte:
# dtrace -s ./intr.d dtrace: script './intr.d' matched 2 probes ^C isp 0 value ------------- Distribution ------------- count 8192 | 0 16384 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1 32768 | 0 pcf8584 0 value ------------- Distribution ------------- count 64 | 0 128 | 2 256 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 157 512 |@@@@@@ 31 1024 | 3 2048 | 0 pcf8584 1 value ------------- Distribution ------------- count 2048 | 0 4096 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 154 8192 |@@@@@@@ 37 16384 | 2 32768 | 0 qlc 0 value ------------- Distribution ------------- count 16384 | 0 32768 |@@ 9 65536 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 126 131072 |@ 5 262144 | 2 524288 | 0 hme 0 value ------------- Distribution ------------- count 1024 | 0 2048 | 6 4096 | 2 8192 |@@@@ 89 16384 |@@@@@@@@@@@@@ 262 32768 |@ 37 65536 |@@@@@@@ 139 131072 |@@@@@@@@ 161 262144 |@@@ 73 524288 | 4 1048576 | 0 2097152 | 1 4194304 | 0 ohci 0 value ------------- Distribution ------------- count 8192 | 0 16384 | 3 32768 | 1 65536 |@@@ 143 131072 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1368 262144 | 0 |
Se você for um desenvolvedor de driver de dispositivo, talvez esteja interessado em criar seus próprios testes do SDT em seu driver do Solaris. O efeito de teste desativado do SDT é essencialmente o custo de várias instruções de máquina não operacionais. Portanto, você é encorajado a adicionar testes do SDT aos seus drivers de dispositivo, se necessário. A menos que estes testes afetem negativamente o desempenho, você pode deixá-los em seu código de envio.
Os testes do SDT são declarados através das macros DTRACE_PROBE , DTRACE_PROBE1, DTRACE_PROBE2, DTRACE_PROBE3 e DTRACE_PROBE4 do <sys/sdt.h>. O nome do módulo e o nome da função de um teste baseado em um SDT correspondem ao módulo do kernel e à função do teste. O nome do teste depende do nome fornecido na macro DTRACE_PROBEn. Se o nome não contiver duas barras inferiores consecutivas (__), o nome do teste será conforme escrito na macro. Se o nome contiver quaisquer duas barras inferiores consecutivas, o nome do teste converterá as barras inferiores consecutivas em um único traço (-). Por exemplo, se uma macro DTRACE_PROBE especificar transaction__start, o teste do SDT será chamado de transaction-start. Esta substituição permite que o código de C forneça nomes de macro que não são identificadores válidos de C sem especificar uma seqüência.
O DTrace inclui o nome do módulo do kernel e o nome da função como parte da tupla que identifica o teste, sendo assim, você não precisa incluir esta informação no nome do teste para evitar colisões de espaço de nome. Você pode usar o comando dtrace -l -P sdt -m módulo em seu módulo do driver para listar os testes que instalou e os nomes completos que serão vistos pelos usuários do DTrace.
Os argumentos de cada teste do SDT são os argumentos especificados na referência de macro DTRACE_PROBEn correspondente. O número de argumentos depende de qual macro foi usada para criar o teste: DTRACE_PROBE1 especifica um argumento, DTRACE_PROBE2 especifica dois argumentos, e assim por diante. Ao declarar seus testes do SDT, você pode minimizar seu efeito de teste desativado, não referenciando os ponteiros e não carregando a partir de variáveis globais nos argumentos do teste. O cancelamento de referência de ponteiro e o carregamento de variável global podem ser feitos com segurança em ações de D que ativam testes, sendo assim, os usuários do DTrace podem solicitar estas ações somente quando necessárias.
O provedor SDT usa o mecanismo de estabilidade do DTrace para descrever suas estabilidades, conforme mostrado na tabela seguinte. 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 |
Privada |
Privada |
ISA |
Argumentos |
Privada |
Privada |
ISA |