2012-01-23 1 views
7

Ho capito che: 1) waitpid è usato per attendere la morte di un bambino e quindi raccogliere il SIGCHLD e lo stato di uscita del bambino ecc. 2) Quando abbiamo un gestore di segnale per SIGCHLD, facciamo ancora alcune cose in relazione alla pulizia del bambino o di altre cose (fino al programmatore) e poi fare un waitpid in modo che il bambino non vada a zombi e poi ritorni.Utilizzo di waitpid o sigaction?

Ora, abbiamo bisogno di avere entrambi 1 e 2 nei nostri programmi quando facciamo un fork/exec e il bambino ritorna? Se abbiamo entrambi, il SIGCHLD è ottenuto prima, in modo che il gestore di segnale viene chiamato prima e quindi la sua waitpid si chiama con successo e non il waitpid nel codice processo padre come segue:

my_signal_handler_for_sigchld 
{ 
do something 
tmp = waitpid(-1,NULL,0); 
print tmp (which is the correct value of the child pid) 
} 

int main() 
{ 
    sigaction(SIGCHLD, my_signal_handler_for_sigchld) 
    fork() 
    if (child) //do something, return 
    if parent // waitpid(child_pid, NULL,0); print value returned from this waitpid - it is -1 
} 

grato se qualcuno mi aiuta capisci questo.

risposta

1

È necessario chiamare le syscalls di attesa come waitpid o gli amici -eg wait4 ecc. In alternativa si può avere zombie processes.

È possibile gestire SIGCHLD per notificare che un bambino è terminato (o interrotto, ecc.) Ma sarà necessario attendere in seguito.

I gestori di segnale sono limitati a chiamare un piccolo set di funzioni di sicurezza del segnale asincrono (vedere signal(7) per ulteriori informazioni). Un buon consiglio è di impostare una bandiera volatile sig_atomic_t all'interno e testarla in luoghi successivi e più sicuri.

18

In realtà non è necessario gestire SIGCHLD se l'intento è eseguire un processo figlio, fare alcune cose, quindi attendere che finisca. In tal caso, devi solo chiamare waitpid quando sei pronto per la sincronizzazione. L'unica cosa che è SIGCHLD è utile per la notifica asincrona della terminazione secondaria, ad esempio se hai un'applicazione interattiva (o daemon a esecuzione prolungata) che genera vari bambini e deve sapere quando finiscono. Tuttavia, SIGCHLD è davvero brutto/brutto anche per questo scopo, poiché se si utilizza un codice di libreria che crea processi figlio, è possibile che gli eventi per i figli della biblioteca terminino e interferiscano con la loro gestione. I gestori di segnale sono intrinsecamente globali a livello di processo e gestiscono lo stato globale, che di solito è A Bad Thing (tm).

Qui ci sono due approcci migliori per quando si dispone di processi figli che saranno di terminazione in modo asincrono:

Approccio 1 (select/poll event-based): Assicurarsi di avere un tubo da/per ogni processo figlio si crea . Può essere il loro stdin/stdout/stderr o solo un dummy extra fittizio. Quando termina il processo secondario, la sua estremità della pipe verrà chiusa e il ciclo di eventi principale rileverà l'attività su quel descrittore di file. Dal momento che ha chiuso, riconosci che il processo figlio è morto e chiama lo waitpid per raccogliere lo zombi.

Approccio 2 (basato sul thread): per ogni processo figlio creato, creare anche un thread che chiamerà immediatamente waitpid sul pid del processo figlio. Quando waitpid restituisce correttamente, utilizzare le primitive di sincronizzazione del thread preferite per consentire al resto del programma di sapere che il bambino è terminato, o semplicemente occuparsi di tutto ciò che è necessario fare in questo thread del cameriere prima che termini.

Entrambi questi approcci sono modulari e compatibili con le librerie (evitano di interferire con altre parti del codice o codice libreria che potrebbero utilizzare i processi figli).

+0

Ciao, grazie per la risposta.Ma quello che stavo veramente cercando è: quando ho sig_handler e waitpid nel processo genitore, il sig_handler è chiamato becaues di sigchld e quindi il secondo waitpid come mostrato sopra nella mia domanda restituisce -1. Quindi posso semplicemente rimuovere il secondo waitpid che sto avendo? – Vin

+0

Sì, è possibile solo attendere una volta un determinato processo figlio. In realtà è un bug da attendere di nuovo poiché il pid è "liberato" dalla prima attesa e potrebbe essere stato riutilizzato per un nuovo processo figlio (se ne è stato creato un altro). –

+0

@R .. Potremmo chiarire il 'Quando il processo figlio termina, la sua estremità del tubo sarà chiusa un po '? Per essere veramente precisi, non sarebbe 'Quando il processo figlio chiude il suo FD che è connesso alla fine del tubo, e non ci sono altri processi con FD collegati a quella estremità del tubo, allora l'altra estremità del tubo sarà segnalato come chiuso (riceve EOF) '? Credo che spiegherebbe più precisamente cosa succede, e anche l'importante caso speciale di ciò che accade se più di 2 processi con FD a una pipe aperta. – nh2