2014-04-24 9 views
6

Nel mio programma, il cui rss è 65G, quando si chiama fork, sys_clone->dup_mm->copy_page_range consumerà più di 2 secondi. In questo caso, una cpu sarà al 100% sys quando si esegue la fork, allo stesso tempo, un thread non può ottenere il tempo di CPU fino al termine della forchetta. La macchina ha 16 CPU, le altre CPU sono inattive.In macchina multi-core, sistema operativo Linux, quando lo scheduler eseguirà la migrazione di un processo a un'altra CPU

Quindi la mia domanda è una CPU occupata su fork, perché lo scheduler non esegue la migrazione del processo in attesa su questa CPU in altre CPU inattiva? In generale, quando e come lo scheduler migra il processo tra cpus?

Cerco questo sito e le discussioni esistenti non possono rispondere alla mia domanda.

+2

Perché pensi che questo altro thread stia morendo di fame per la cpu? Può essere che stia dormendo su qualche risorsa/blocco di memoria, non disponibile durante la forchetta. – oakad

+0

scusa, la mia descrizione non è chiara. In realtà, il thread wait-cpu è il mio thread IO, che invia/riceve pacchetto dal client, nella mia osservazione, il pacchetto esiste sempre, ma il thread IO non può riceverlo. con l'aiuto di systemtap, trovo che il thread IO non può ottenere il tempo della CPU. Posso trovare una CPU con il 100% sys (fare sys_clone), allo stesso tempo, l'altra CPU è inattiva. – Raymond

+0

'sys_clone' potrebbe bloccare alcuni mutex del kernel mentre si esegue' dup_mm' ('pi_lock' o' mm-> mmap_sem'), e il thread I/O deve bloccare lo stesso mutex/semaforo. Cerca di ottenere stack (kernel o utente) per il secondo thread ... (Sei sicuro che solo 'fork' potrebbe funzionare per te? Prova vfork + exec =' posix_spawn', se c'è exec appena dopo il fork.) – osgx

risposta

2

rss è 65G, quando la chiamata fork, sys_clone-> dup_mm-> copy_page_range consumerà più di 2 secondi

Mentre si fa fork (oppure clone) i vma del processo esistente devono essere copiati in vmas di un nuovo processo. dup_mm function (kernel/fork.c) crea nuovo mm e fa la copia effettiva. Non ci sono chiamate dirette a copy_page_range, ma penso che static function dup_mmap possa essere inserito in dup_mm e che abbia chiamate a copy_page_range.

Nel dup_mmap ci sono diverse serrature bloccate, sia in nuovi mm e vecchio oldmm:

356   down_write(&oldmm->mmap_sem); 

dopo l'assunzione del mmap_sem lettore/scrittore di semaforo, c'è un ciclo su tutti i mmaps a copiare il loro metainformazione:

381   for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) 

Solo dopo il ciclo (è lunga nel tuo caso), mmap_sem è sbloccato:

0.123.516,41 mila
465 out: 
468   up_write(&oldmm->mmap_sem); 

Mentre il rwlock mmap_sep è inattivo dallo scrittore, nessun altro lettore o scrittore può fare nulla con mmaps in oldmm.

un thread non può ottenere il tempo di CPU fino a completare la forcella Quindi la mia domanda è una CPU era occupato sulla forcella, il motivo per cui lo scheduler non migrare il processo in attesa di questa CPU per altre cpu di inattività?

Sei sicuro, che altro thread è pronto a correre e non voler fare nulla con mmaps, come:

  • mmaping qualcosa di nuovo o unmapping qualcosa non necessario,
  • crescita o in calo la sua heap (brk),
  • crescere il proprio stack
  • pagefaulting
  • o molte altre attività ...?

In realtà, il filo di attesa-cpu è il mio filo IO, che inviano/ricevono il pacchetto dal client, nella mia osservazione, il pacchetto esiste sempre, ma il filo IO non può riceverlo.

Si dovrebbe verificare lo stack del thread wait-cpu (c'è anche SysRq per questo) e il tipo di I/O. mmap di file è la variante di I/O che verrà bloccata su mmap_sem tramite fork.

Inoltre, è possibile controllare "l'ultima CPU utilizzata" del thread wait-cpu, ad es. nell'utility di monitoraggio top, abilitando la visualizzazione thread (chiave H) e aggiungendo la colonna "Ultima CPU utilizzata" all'output (fj nei precedenti; f scorrere fino a P, immettere in più recente). Penso che sia possibile che il thread wait-cpu fosse già sull'altra CPU, solo che non è permesso (non pronto) per l'esecuzione.

Se si utilizza forcella solo per fare exec, può essere utile:

  • o passare a vfork + exec (o semplicemente per posix_spawn). vfork will suspend il processo (ma may not suspend your other threads, it is dangerous) fino a quando il nuovo processo eseguirà exec o exit, ma l'esecuzione potrebbe essere più veloce dell'attesa di 65 GB di mmaps da copiare.
  • oppure non eseguire fork dal processo multithread con diversi thread attivi e memoria virtuale multi-GB. È possibile creare un processo di supporto piccolo (senza multi-GB mmaped), comunicare con esso utilizzando ipc o socket o pipe e chiedere di fork e fare tutto quello che vuoi.
Problemi correlati