O primeiro artigo desta série foca principalmente o funcionamento do SystemTap e como ele faz internamente para prover as funcionalidades requeridas pelos usuários.
Neste artigo será tratado a segunda parte do tópico sobre SystemTap, onde será descrito a linguagem de referência e o modo guru.
Muito da sintáxe da linguagem do SystemTap tem a ver com uma mistura de C com AWK, e para qualquer programador de nível básico, é possivel comecar a trabalhar com a ferramenta sem muitas dificuldades.
Uma das principais caracteristicas da linguagem é que ela é fracamente tipada, isto é, nào usa definição de tipo de variável. Assim sendo, para definir uma variável, basta utiliza-lá, da seguinte forma:
probe begin{
var1 = "Hello"
var2 = 1
printf("%s %d\n", var1, var2)
}
|
Veja que neste exemplo, foi criada duas variáveis var1 and var2, e cada um tem um tipo. Veja que a variável é inicializada com uma string Hello, e portanto a variável var1 será do tipo string. Por outro lado, a variável var2 foi definida com um valor 1, e será do tipo inteiro. Note que também a função printf se comporta exatamente igual à função em C.
Note que para sair de um script , também é utilizada a função exit() que também se comporta igualmente em C.
Nesta sub seção será introduzido o conceito de funções afim de tornar o processo de programação fácil. Para definir uma função em SystemTap basta seguir o seguinte esqueleto.
function bigger (x, y) {
if (x > y)
return x
else
return y
}
|
Neste exemplo, é possível foi definida a função bigger que recebe dois argumentos, x e y. A função basicamente compara os dois número e retorna o maior dos dois. Note que não é necesário definir o tipo de parametro nem o retorno de função, uma vez que a linguagem é fracamente tipada.
A linguagem SystemTap também permite a chamada de funções recursivas, o que torna a ferramenta muito poderosa. Segue um examplo do cálculo de fibonacci utilizando funções recursivas:
function fibonacci(i) {
if (i < 1) error ("bad number")
if (i == 1) return 1
if (i == 2) return 2
return fibonacci (i-1) + fibonacci (i-2)
}
probe begin {
printf ("O décimo primeiro número de fibonacci é: %d", fibonacci (11))
exit ()
}
|
Note que esse script vai gerar algo do tipo:
O décimo primeiro número de fibonacci é: 118
O SystemTap permite a utilização de modo guru, que proporciona várias flexibilidades avançadas para fazer probes, além de poder usar a linguagem C como linguagem de programação da ferramenta. Note que não é necessário a codificação em C quando utiliza-se o modo guru, pode-se continuar a utilizar a linguagem própria do SystemTap.
O SystemTap tem inúmeros métodos de proteção para memória e dados que não permitem que um script mal construido instabilize o sistema, ou mesmo, trave a máquina. Quando utilizado o modo guru, todas essas proteções são desativadas, e a partir disto, é possível que seja feita qualquer alteração no sistema, como por exemplo, mudar uma variável global ou mesmo alterar parâmetros de funções, tais como chamadas de sistema ou parametros do escalonador.
Além de fazer probes mais poderosos, o modo guru permite também que se teste algum novo fix novo do sistema, alterando a parte problemática com um pedaço de um probe do SystemTap, alterando assim o comportamento geral do sistema.
Afim de utilizar o modo guru, é preciso passar o parâmetro -g na linha de comando quando for chamar o script, assim:
# stap -g meu_script_guru.stp
|
3.1 Alterando parâmetros de funções
A seguir será construido um script que altera um parâmetro da chamada de sistema write. Note que chamada de sistema write contém um argumento chamado buf que é o buffer com os dados usados na escrita, assim sendo, se esse buffer for mudado, a escrita também passará a ser mudada, independentemente de onde aconteça no sistema e qual usuário está utilizando a chamada de sistema, isto é, uma mudança global.
Neste caso, toda vez que a função for chamada, será verificado se o que for escrito é SystemTap, e caso seja, o parâmetro buffer será deslocado em seis posições.
Segue o diagrama que mostra o que será feito com a chamada:
Segue o script que faz essa alteração:
probe syscall.write {
if (isinstr(user_string($buf),"SystemTap")){
$buf = $buf + 0x06 // desloca em 6
}
}
|
Neste caso, a variável buf será alterada, e toda vez que a chamada de sistema write for chamada contendo a palavra SystemTap , ele deixará de imprimir os seis primeiros caracteres, e imprimirá somente Tap, como o exempo a seguir.
# echo SystemTap
Tap
|
Neste caso especifico, o comando simplesmente deveria imprimir o que foi requisitado, mas como o script acima estará rodando, ele imprimirá somente Tap. Note que isso valerá para qualquer lugar que o sistema estiver gravando, como por exemplo, em um socket de rede, em um arquivo ou em qualquer outro lugar que tenho um file descriptor associado.
3.2 Alterando valor de retorno
Assim como é possível alterar valores de parâmetros, também é possível alterar os valores de retorno das funçòes, isto é, quando o kernel executa uma função (ou chamada de sistema), é retornado um número que demonstra se a função executou corretamente ou não, e esse número pode ser modificado.
No próximo exemplo, modificaremos o valor de retorno da chamada de sistema que cria diretórios, isto é, a chamada sys_mkdir. Neste exemplo em especifico, será retornado o valor -1, que é um valor de erro, toda vez que um diretório que contenha a palavra foobar. Assim sendo, em todos os outros casos a chamada sys_mkdir funcionará perfeitamente, exceto se algum usuário/software tentar criar um diretório que contenha a palavra foobar. Segue o script:
probe kernel.function("sys_mkdir").return{
if (isinstr(user_string($pathname),"foobar")){
$return = -1
}
}
|
Note que esse script utiliza a função sys_mkdir, que é identica a chamada por syscall.mkdir.
Abaixo está um console tentando executar uma sequencia de comando:
# mkdir foobar
# rm -fr foobar
# stap -g change_return_mkdir.stp &
# mkdir foobar
mkdir: cannot create directory `foobar': Permission denied
# echo $?
-1
|
Note que assim que o script comecar a rodar, todo o usuário ou software que tentar cirar um diretório que contenha a string foobar, receberá um erro. Note que o leitor atento perceberá que somente a variável de retorno mudou, isto é, a função foi executada com sucesso, porém o retorno foi mudado, isso implica que o diretório foi criado, embora tenha-se recebido -1 de retorno de função
Embora pouco utilizado, existe uma GUI para o SystemTap que pode ser util para vários usuários iniciantes, principalmente por causa da função de autocompletion e de mostrar os erros conforme vai-se escrevendo o código. A ferramenta também possui features de visualização de dados, que torna os graficos e agregadores muito mais fáceis de serem vistos. A ferramenta foi desenvolvida com base no Eclipse e pode ser encontrada no SourceForge com o nome de SystemTap GUI.
Abaixo é demonstrado a feature de autocompletion:
.
Note que também é possível vizualizar os dados coletados pelo SystemTap de uma maneira mais bonita quando utiliza-se o modo gráfico, como por exemplo a figura abaixo mostrando a distribuição de um evento.
Gostaria de agradecer à IBM pela oportunidade de trabalhar no projeto, e ao Klaus Kiwi pela revisão técnica.
- SystemTap: Instrumenting the Linux Kernel for Analyzing Performance and Functional Problems - http://www.redbooks.ibm.com/abstracts/redp4469.html
- SystemTap Beginners Guide - http://sourceware.org/systemtap/SystemTap_Beginners_Guide.pdf
- SystemTap wiki - http://sourceware.org/systemtap/wiki