Localize ocasionais hog do kernel da CPU

11

Eu tenho um kernel 2.6.35 PREEMPT em execução no processador ARMv7 de velocidade moderada. Aproximadamente uma vez a cada 100 - 125s, algo faz com que o kernel falhe ao processar alguns drivers relacionados ao áudio com a rapidez necessária para evitar falhas. A espera geralmente varia de 15 a 30 ms, mas pode demorar muito mais. Não está claro se a retenção está totalmente no kernel ou pode estar relacionada ao agendamento de um processo do usuário em execução com prioridade em tempo real (SCHED_RR, 2).

Meu palpite é que existe um (pelo menos um) driver que não está se saindo bem com a preempção.

Alguma saída de rastreio do processo do usuário ilustra algum aspecto do comportamento normal e anormal, embora eu não tenha certeza de como interpretar os vários relatórios de tempo?

Caso normal:

     Pesquisa de 0,000518 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3415) = 1 
     Pesquisa 0.010202 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventos = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3404) = 1 
     Pesquisa 0.000585 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventos = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3404) = 1 
     Pesquisa de 0,000302 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3404) = 1 
     Pesquisa 0.010706 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventos = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3393) = 1 
     Pesquisa de 0,000480 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventos = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3392) = 1 

Nenhum bloqueio ocorre na pesquisa de saída no fd6 e, quando apenas o fd10 é pesquisado para entrada, ocorre um bloco de cerca de 10ms. Isso se reflete no relatório da duração da chamada do sistema e no intervalo entre as chamadas do sistema (elas são consistentes).

Caso de falha (exemplo extremo):

     Pesquisa de 0,000305 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3543) = 1 
     Pesquisa 0,010730 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventos = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3533) = 1 
     Pesquisa de 0,000475 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventos = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3532) = 1 
     Pesquisa de 0,000329 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3532) = 1 
     Pesquisa de 0,953349 ([{fd = 10, eventos = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventos = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT | POLLERR}], 2, 2578) = 1 

Observe neste caso que, embora a segunda última chamada seja gravada em 10 ms (normal), é 953 ms antes da última chamada.

Quais ferramentas posso usar para rastrear o culpado?

awy
fonte
2
Pontos de bônus para a pergunta interessante. Não tenho certeza de como responder, mas tenho uma pergunta sobre como rastrear o uso da CPU (em oposição aos picos no iowait, por exemplo)?
Bratchley
1
O primeiro palpite é se você estiver executando o JFFS2 ou YAFFS em um flash NAND grande, especialmente se estiver gravando. Desative qualquer coisa que escreva para piscar e veja se isso ajuda. Como é a sua tabela de processos? Você pode usar o ftrace como último recurso se tiver uma cadeia de ferramentas para construir o kernel.
Jonathan Ben-Avraham
sar-Bu pode fazê-lo .. linux.die.net/man/1/sar
Grizly
Há algum flash em uso; um cartão SD com um sistema de arquivos ext4 montado. E as gravações são de fato uma possível fonte desses problemas (mas por que exatamente?), Mas provavelmente não é a única.
awy

Respostas:

1

perfpode ser útil para você. Faz parte dos utilitários do kernel do linux.

Por exemplo:

perf record -R -a -g fp -e cycles -e syscalls:sys_enter_poll -e syscalls:sys_exit_poll
#Just ctrl+c if you are done, and view ith
perf script 

Ele mostrará todos os tempos e parâmetros de entrada / saída do syscall (como strace), fornecerá o nome do binário que está chamando o syscall e fará uma amostra da pilha de chamadas de cada CPU em alguma frequência (incluindo símbolos do kernel). Então você pode realmente ver qual código foi executado durante o syscall. Em um sistema multiprocessador, você precisa prestar atenção ao ID da CPU (por exemplo, [001]).

Zulan
fonte
Vou dar uma olhada na criação do perf para a plataforma - obrigado pela dica.
22413 awy
0

Talvez atoppossa lançar alguma luz sobre o seu problema.

Ele pode mostrar os processos que já foram encerrados e a CPU , memória , disco e utilização da rede .

Você pode executá-lo de maneira interativa, deixá-lo gravar em um arquivo de texto ou executá-lo como sarem um intervalo predefinido, criando um arquivo de histórico binário pelo qual você poderá avançar posteriormente.

Eu o uso para encontrar porcos de todos os tipos que são difíceis de encontrar :-)

trapicki
fonte