Perché un figlio di un vfork o fork dovrebbe chiamare _exit () invece di exit ()?


12

Dalla pagina man di vfork():

vfork () differisce da fork () in quanto il genitore è sospeso fino a quando il figlio non effettua una chiamata per eseguire (2) o _exit (2). Il figlio condivide tutta la memoria con il suo genitore, incluso lo stack, fino a quando execve () viene emesso dal figlio. Il bambino non deve tornare dalla funzione corrente o chiamare exit (), ma può chiamare _exit ().

Perché il bambino dovrebbe usare un _exit()piuttosto che semplicemente chiamare exit()? Spero che questo sia applicabile a entrambi vfork()e fork().


2
se sei interessato a una discussione
xenoterracide

Risposte:


11

Come visto in precedenza , vforknon consente al processo figlio di accedere alla memoria del genitore. exitè una funzione di libreria C (ecco perché è spesso scritta come exit(3)). Esegue varie attività di pulizia come lo svuotamento e la chiusura di flussi C (i file si aprono tramite le funzioni dichiarate in stdio.h) e l'esecuzione delle funzioni specificate dall'utente registrate con atexit. Tutte queste attività comportano la lettura e la scrittura nella memoria di processo.

_exitesce senza pulizia. È direttamente una chiamata di sistema (motivo per cui è scritta come _exit(2)), in genere implementata inserendo il numero di chiamata di sistema in un registro del processore ed eseguendo una specifica istruzione del processore (diramazione al gestore delle chiamate di sistema). Non è necessario accedere alla memoria di processo, quindi è sicuro farlo dopo vfork.

Dopo fork, non vi sono restrizioni di questo tipo: il processo genitore e figlio sono ora completamente autonomi.


vfork non consente al processo figlio di accedere alla memoria del genitore ? Ma ho pensato che condividessero lo stesso spazio degli indirizzi, in modo che il bambino potesse accedere allo spazio degli indirizzi dei genitori. È stata una comprensione sbagliata?
Sen

Dopo il fork, non vi è tale restrizione: il processo genitore e figlio sono ora completamente autonomi. Significa che posso chiamare un'uscita () da un figlio di un fork?
Sen,

1
@Sen: al bambino non è consentito accedere alla memoria del genitore. Se lo provi, potrebbe funzionare, perché il kernel non ti proteggerà. Ma l'effetto potrebbe non essere quello che intendi; ad esempio, se il compilatore decide di lasciare un valore in un registro, non verrà visualizzato dal processo padre.
Gilles 'SO- smetti di essere malvagio' il

@Sen: dopo un fork, è possibile effettuare l'uscita di chiamata o qualsiasi altra funzione. Ogni processo inizia dopo un fork (su Linux, anche il processo iniziale initè biforcuto dal kernel).
Gilles 'SO- smetti di essere malvagio' il

3

exiteseguire ulteriori operazioni di pulizia come le funzioni di chiamata registrate, atexitquindi accede ai dati all'esterno della parte copiata. _exitesegue syscall direttamente senza alcuna pulizia, tranne che nel kernel.


... e va notato che fork () copia tutto, quindi potresti essere in grado di chiamare exit (), e puoi sicuramente tornare dalla funzione corrente.
derobert,

3

Hai il figlio che chiama _exit () per evitare di svuotare i buffer stdio (o altri) quando termina il processo figlio. Poiché il processo figlio costituisce una copia esatta del processo padre, il processo figlio ha ancora tutto ciò che il padre aveva in "stdout" o "stderr", i buffer da <stdio.h>. Puoi (e otterrai, in momenti inopportuni) ottenere doppi output chiamando exit (), uno dai gestori atexit del processo figlio e uno dal genitore, quando i buffer nel processo genitore si riempiono e vengono svuotati.

Mi rendo conto che la risposta di cui sopra si concentra su specifiche stdio.h, ma quell'idea probabilmente si ripercuote su altri I / O con buffer, proprio come indica una delle risposte sopra.


1

exit(): - esegue alcune attività di cleanup, come chiudere i flussi di I / o e molti, e poi ritorna al kernel. _exit(): - arriva direttamente al kernel (non eseguire alcuna operazione di pulizia).

fork() : sia padre che figlio hanno una tabella di file diversa, quindi le modifiche apportate da figlio non influiscono sui parametri di ambiente di padre e viceversa.

vfork(): sia padre che figlio utilizzano la stessa tabella di file, quindi la modifica apportata da figlio influenza i parametri di ambiente di padre. ad es. alcune variabili var=10, ora gestite var++da child e quindi eseguono parent, puoi vedere l'effetto di anche var++nell'output di parent.

Come ho detto, se si utilizza exit()in vfork()poi tutti gli I / O è già chiuso. Quindi, anche se parent funziona correttamente, non è possibile ottenere l'output corretto, poiché tutte le variabili vengono scaricate e tutti i flussi chiusi.

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.