2009-07-21 14 views
28

Per i processi figlio, è possibile utilizzare le funzioni wait() e waitpid() per sospendere l'esecuzione del processo corrente fino all'uscita di un figlio. Ma questa funzione non può essere utilizzata per processi non secondari.Come attendere l'uscita di processi non secondari

C'è un'altra funzione, che può attendere l'uscita di qualsiasi processo?

risposta

25

Niente equivalente a wait(). La prassi abituale consiste nel sondare utilizzando kill(pid, 0) e cercare il valore restituito -1 e errno di ESRCH per indicare che il processo è terminato.

+2

È corretto avere un tale ciclo di occupato? – CsTamas

+1

Beh, non vuoi renderlo troppo occupato; dovresti 'usleep()' per un po 'dopo ogni 'kill()' che non trova il processo andato. Quindi devi trovare un equilibrio tra quanto è impegnato il sondaggio e quanto tempo è bene che il processo sia finito prima che tu lo noti. – chaos

+0

Oh, 'usleep()' è diventato obsoleto mentre non guardavo, apparentemente. Sembra che dovresti ora 'nanosleep()' invece. – chaos

2

Nessuno di cui sono a conoscenza. Oltre alla soluzione del caos, puoi usare i semafori se puoi cambiare il programma che vuoi aspettare.

Le funzioni di libreria sono sem_open(3), sem_init(3),sem_wait(3), ...

sem_wait(3) esegue un'attesa, in modo da Non ha a che fare di attesa occupato come in soluzione CAOS FELICE'. Ovviamente, l'uso dei semafori rende i programmi più complessi e potrebbe non valerne la pena.

+0

Questi semafori sono praticamente inutili, in quanto persistono anche se nessun processo li ha aperti. Ricordo di aver chiamato per sempre ipcrm per ripulire gli avanzi di alcuni processi in crash. –

4

Si potrebbe anche creare un socket o un FIFO e leggerli. La FIFO è particolarmente semplice: collega l'output standard di tuo figlio con FIFO e leggi. La lettura bloccherà fino a quando il bambino non esce (per qualsiasi motivo) o finché non emette alcuni dati. Quindi avrai bisogno di un piccolo ciclo per scartare i dati di testo indesiderati.

Se si ha accesso alla fonte del bambino, aprire la FIFO per scrivere quando inizia e poi semplicemente dimenticarsene. Il sistema operativo pulirà il descrittore di file aperto quando il bambino termina e il processo "genitore" in attesa si sveglierà.

Ora questo potrebbe essere un processo che non hai avviato o non possiedi. In tal caso, è possibile sostituire l'eseguibile binario con uno script che avvia il binario reale ma aggiunge anche il monitoraggio come spiegato sopra.

+2

Ma il processo non è un bambino ... – LtWorf

+0

Non un bambino e in particolare potrebbe non essere progettato pensando a questo monitoraggio e non in grado di modificare il codice sorgente. – Lothar

+0

@Lothar Penso che sia opportuno mostrare alcune soluzioni al di fuori dell'ovvio, soprattutto perché la risposta accettata è inaffidabile. Inoltre, qualsiasi processo può essere trasformato in un bambino in qualche modo. Ad esempio, è possibile sostituire il file binario con uno script che monitora il file binario originale e invia un segnale quando l'ora-bambino muore. –

1

Forse potrebbe essere possibile attendere che/proc/[pid] o/proc/[pid]/[qualcosa] scompaiano?

Ci sono poll() e altre funzioni di attesa evento file, forse che potrebbe essere d'aiuto?

+0

Sì, è una buona idea. A meno che lo stesso id di processo non venga riutilizzato così rapidamente - ma probabilmente questo accade raramente a – CsTamas

+0

@CsTamas, esiste una protezione in cui il numero di identificatori di processo (32768) è molto più grande del numero di processi che possono essere eseguiti. Quindi la probabilità di ottenere lo stesso identificatore di processo è veramente bassa, a meno che non ti addormenti per un po '. –

3

È possibile allegare al processo con ptrace(2). Dalla shell, strace -p PID >/dev/null 2>&1 sembra funzionare. Questo evita l'attesa, anche se rallenterà il processo di tracciamento e non funzionerà su tutti i processi (solo il tuo, che è un po 'meglio dei soli processi figli).

+1

La conoscenza non nuoce mai, ma per le shell, raccomando il modo "standard", eseguendo periodicamente il polling; vedi [domanda 1058047] (http://stackoverflow.com/questions/1058047/wait-for-any-process-to-finish). Anche se può essere un caso raro, ma strace può fare un ciclo occupato. Ad esempio $ (leggi) &; strace -p $!Si noti che (leggi) e se stesso è innocuo. –

12

Su BSD e OS X, è possibile utilizzare kqueue con EVFILT_PROC + NOTE_EXIT per fare esattamente questo. Nessun sondaggio richiesto. Sfortunatamente non esiste un equivalente Linux.

+5

Vergogna su Linux che non hanno portato il kqueue. – Lothar

6

Finora ho trovato tre modi per fare questo su Linux:

  • Polling: si controlla l'esistenza del processo di tanto in tanto, sia utilizzando kill o testando per l'esistenza di /proc/$pid , come nella maggior parte delle altre risposte
  • Utilizzare la chiamata di sistema ptrace per connettersi al processo come un debugger in modo da essere avvisato quando esce, come in a3nm's answer
  • Utilizzare l'interfaccia netlink di ascoltare per PROC_EVENT_EXIT messaggi - in questo modo il k Il kernel dice al tuo programma ogni volta che un processo termina e tu aspetti solo il giusto ID di processo. Ho visto solo questo descritto in one place on the internet.

Plug vergognoso: sto lavorando a un program (open source of course; GPLv2) che fa uno dei tre.

Problemi correlati