Individua il porco occasionale del kernel della CPU


11

Ho un kernel PREEMPT 2.6.35 in esecuzione su processore ARMv7 a velocità moderata. Circa una volta ogni 100 - 125 secondi, qualcosa impedisce al kernel di elaborare alcuni driver relativi all'audio in modo sufficientemente rapido per evitare i underrun. I hold-up sono generalmente nell'intervallo 15-30ms, ma possono essere molto più lunghi. Non è chiaro se il hold-up sia interamente nel kernel o possa essere correlato alla pianificazione di un processo utente in esecuzione con priorità in tempo reale (SCHED_RR, 2).

La mia ipotesi è che esiste un (almeno uno) driver che non sta giocando bene con preempt.

Qualche output di traccia dal processo utente illustra alcuni aspetti del comportamento normale e anormale, anche se non sono sicuro di come interpretare i vari rapporti temporali?

Caso normale:

     0.000518 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3415) = 1 
     0,010202 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL}, {fd = 6, events = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3404) = 1 
     0.000585 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL}, {fd = 6, events = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3404) = 1 
     0.000302 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3404) = 1 
     0,010706 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL}, {fd = 6, events = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3393) = 1 
     0.000480 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL}, {fd = 6, events = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3392) = 1 

Non si verifica alcun blocco nel polling per l'output su fd6 e, quando viene eseguito il polling solo per fd10 per l'input, si verifica un blocco di circa 10 ms. Ciò si riflette sia nel rapporto sulla durata della chiamata di sistema sia nell'intervallo tra le chiamate di sistema (sono coerenti).

Caso di errore (esempio estremo):

     0.000305 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3543) = 1 
     0,010730 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL}, {fd = 6, events = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3533) = 1 
     0.000475 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL}, {fd = 6, events = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT}], 2, 3532) = 1 
     0.000329 sondaggio ([{fd = 10, events = POLLIN | POLLERR | POLLNVAL, revents = POLLIN}], 1, 3532) = 1 
     0.953349 sondaggio ([{fd = 10, eventi = POLLIN | POLLERR | POLLNVAL}, {fd = 6, eventi = POLLOUT | POLLERR | POLLNVAL, revents = POLLOUT | POLLERR}], 2, 2578) = 1 

Notare in questo caso che, sebbene la penultima chiamata sia registrata come 10ms (normale), sono 953ms prima dell'ultima chiamata.

Quali strumenti posso usare per rintracciare il colpevole?


2
Punti bonus per l'interessante domanda. Non sono sicuro di come rispondere, ma ho una domanda su come rintracciarlo all'utilizzo della CPU (al contrario dei picchi di iowait, ad esempio)?
Bratchley,

1
La prima ipotesi è se si esegue JFFS2 o YAFFS su un flash NAND di grandi dimensioni, soprattutto se si sta registrando. Disabilita tutto ciò che scrive in flash e vedi se questo aiuta. Com'è la tua tabella dei processi? Puoi usare ftrace come ultima risorsa se hai una toolchain per compilare il kernel.
Jonathan Ben-Avraham,

sar -bu potrebbe farlo .. linux.die.net/man/1/sar
Grizly

C'è qualche flash in uso; una scheda SD con un filesystem ext4 montato. E scrive ad esso sono davvero una possibile fonte di questi problemi (ma perché, esattamente?) Ma probabilmente non l'unico.
terribile

Risposte:


1

perfpuò essere utile per te. Fa parte delle utility del kernel di Linux.

Per esempio:

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 

Mostrerà tutti i tempi e i parametri di entrata / uscita di syscall (come lo strace), fornirà il nome del binario che invoca la syscall e campionerà il callstack di ciascuna CPU a una certa frequenza (compresi i simboli del kernel). Quindi puoi effettivamente vedere quale codice è stato eseguito durante il syscall. In un sistema multiprocessore è necessario prestare attenzione all'id del CPU (ad es. [001]).


Vedrò come realizzare perf per la piattaforma - grazie per la punta.
terribile

0

Forse atoppuoi far luce sul tuo problema.

Può mostrare i processi che sono già usciti e può mostrare l' utilizzo di CPU , memoria , disco e rete .

È possibile eseguirlo interattivo, lasciarlo scrivere su un file di testo o eseguirlo come sarin un intervallo predefinito, creando un file cronologico binario che è possibile scorrere in seguito.

Lo uso per trovare maiali di tutti i tipi che sono difficili da trovare :-)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.