O DTrace permite o rastreio em contextos altamente restritos no kernel. Em particular, o DTrace permite o rastreio em contextos nos quais a alocação de memória pelo software do kernel possa não ser confiável. A conseqüência dessa flexibilidade de contexto é que sempre existe a possibilidade de que o DTrace irá tentar rastrear os dados quando não houver espaço disponível. O DTrace deve ter uma política para lidar com tais situações quando elas ocorrerem, mas você pode querer ajustar a política com base nas necessidades de um determinado experimento. Algumas vezes a política apropriada pode ser de descartar os novos dados. Outras vezes, talvez seja desejável reutilizar o espaço que contém os dados registrados mais antigos para rastrear novos dados. Mais freqüentemente, a política desejada é de minimizar a probabilidade de ficar sem espaço disponível em primeiro lugar. Para acomodar todas essas demandas, o DTrace oferece suporte a várias políticas de buffer diferentes. Esse suporte é implementado com a opção bufpolicy, e pode ser definido em uma base por consumidor. Consulte o Capítulo 16Opções e ajustáveis para obter detalhes sobre as opções de configuração.
Por padrão, o buffer principal possui uma política switch. Nessa política, os buffers por CPU são alocados em pares: um buffer é ativo e ou outro, inativo. Quando um consumidor do DTrace tenta ler um buffer, o kernel primeiro alterna os buffers inativos e ativos. A alternância de buffer é feita de tal maneira que não haja uma janela na qual os dados do rastreio possam se perder. Depois que os buffers forem alternados, o buffer recém-inativo é copiado para o consumidor do DTrace. Essa política garante que o consumidor sempre veja um buffer auto-consistente: um buffer nunca é simultaneamente rastreado e copiado. Essa técnica também impede que seja introduzida uma janela na qual o rastreio seja pausado ou, de alguma forma, impedido. A taxa na qual o buffer é alternado e lido é controlada pelo consumidor com a opção switchrate. Assim como com qualquer opção de taxa, switchrate pode ser especificada com qualquer sufixo de tempo, mas o padrão é taxa por segundo. Para obter mais detalhes sobre switchrate e outras opções, consulte o Capítulo 16Opções e ajustáveis.
Para processar o buffer principal no nível do usuário mais rápido que o padrão que é de uma vez por segundo, ajuste o valor de switchrate. O sistema processa as ações que produzem atividade no nível do usuário (como printa () e system()) quando o registro correspondente no buffer principal é processado. O valor de switchrate determina a velocidade na qual o sistema processa tais ações.
Na política switch, se um determinado teste ativado rastrear mais dados do que o espaço disponível no buffer principal ativo, os dados serão cancelados e uma contagem de cancelamento por CPU é incrementada. No caso de um ou mais cancelamentos, o dtrace(1M) exibe uma mensagem similar ao seguinte exemplo:
dtrace: 11 drops on CPU 0 |
Se um determinado registro for maior que o tamanho total do buffer, o registro será cancelado independentemente da política do buffer. Você pode reduzir ou eliminar cancelamentos, seja aumentando o tamanho do buffer principal com a opção bufsize ou aumentando a taxa de alternância com a opção switchrate .
Na política switch, o espaço temporário para copyin(), copyinstr() e alloca() é alocado fora do buffer ativo.
Para alguns problemas, você pode querer usar um único buffer em kernel. Embora essa abordagem possa ser implementada com a política switch e construções apropriadas de D incrementando-se uma variável em D e criando-se um predicado para uma ação exit() apropriadamente, tal implementação não elimina a possibilidade de cancelamentos. Para solicitar um único buffer grande em kernel e prosseguir com o rastreio até que um ou mais dos buffers por CPU tenha sido preenchido, use a política de buffer fill. Nessa política, o rastreio continua até que um teste ativado tente rastrear mais dados que possam caber no espaço restante do buffer principal. Quando não houver espaço suficiente restante, o buffer é marcado como preenchido e o consumidor é notificado que pelo menos um dos buffers por CPU foi preenchido. Quando o dtrace(1M) detecta um único buffer preenchido, o rastreio é interrompido, todos os buffers são processados e dtrace é encerrado. Dados adicionais não serão rastreados para um buffer preenchido mesmo que esses dados caibam nele.
Para usar a política fill, defina a opção bufpolicy como fill. Por exemplo, o seguinte comando rastreia cada entrada de chamada do sistema em um buffer por CPU de 2K com a política de buffer definida como fill:
# dtrace -n syscall:::entry -b 2k -x bufpolicy=fill |
Os testes END normalmente não são acionados até que o rastreio tenha sido explicitamente interrompido pelo consumidor do DTrace. É garantido que os testes END sejam acionados apenas em uma CPU, mas a CPU na qual o teste é acionado não é definida. Com buffers fill, o rastreio é explicitamente interrompido quando pelo menos um dos buffers principais por CPU tiver sido marcado como preenchido. Se a política fill estiver selecionada, o teste END pode ser acionado em uma CPU que possua um buffer preenchido. Para acomodar o rastreio END em buffers fill, o DTrace calcula a quantidade de espaço potencialmente consumido pelos testes END e subtrai esse espaço do tamanho do buffer principal. Se o tamanho líquido for negativo, o DTrace se recusará a iniciar e o dtrace(1M) retornará uma mensagem de erro correspondente:
dtrace: END enablings exceed size of principal buffer |
O mecanismo de reserva garante que um buffer completo sempre possui espaço suficiente para quaisquer testes END.
A política de buffer ring do DTrace auxilia no rastreio de eventos que levam a falha. Se a reprodução da falha demorar horas ou dias, talvez você queira manter somente os dados mais recentes. Depois que um buffer principal for preenchido, o rastreio retorna para a primeira entrada, sobrescrevendo dados de rastreio antigos. Estabeleça o buffer de anel, configurando a opção bufpolicy para a seqüência ring:
# dtrace -s foo.d -x bufpolicy=ring |
Quando usado para criar um buffer de anel, o dtrace(1M) não exibirá qualquer resultado até que o processo esteja terminado. Nesse momento, o buffer de anel estará consumido e processado. O dtrace processa cada buffer de anel em ordem de CPU. Em um buffer de CPU, os registros do rastreio serão exibidos na ordem do mais antigo para o mais novo. Assim como na política de buffer switch, não existe ordem entre os registros de CPUs diferentes. Se for necessária uma ordem, você deve rastrear a variável timestamp como parte da solicitação de rastreio.
O exemplo a seguir demonstra o uso de uma diretiva #pragma option para ativar o buffer em anel:
#pragma D option bufpolicy=ring #pragma D option bufsize=16k syscall:::entry /execname == $1/ { trace(timestamp); } syscall::rexit:entry { exit(0); }