fork () e output

Ho un programma semplice:

int main() { std::cout << " Hello World"; fork(); } 

Dopo che il programma è stato eseguito, il mio risultato è: Hello World Hello World . Perché succede questo invece di un unico Hello world ? Immagino che il processo figlio venga rieseguito dietro le quinte e che il buffer di output sia condiviso tra i processi o qualcosa del genere, ma che il caso o qualcos’altro sta accadendo?

Questo non è esattamente quello che pensavi in ​​origine. Il buffer di output non è condiviso – quando si esegue il fork, entrambi i processi ottengono una copia dello stesso buffer . Quindi, dopo il fork, entrambi i processi eliminano il buffer e stampano i contenuti sullo schermo separatamente.

Questo succede solo perché cout è bufferato IO . Se hai usato cerr, che non è bufferizzato, dovresti vedere il messaggio solo una volta, pre-fork.

l’output standard utilizza IO bufferizzato. Quando viene chiamato fork() l’output standard non viene svuotato e il contenuto bufferizzato viene replicato nel processo figlio. Questi buffer vengono svuotati all’uscita del processo, con la conseguente visualizzazione delle due uscite.

Se cambi il programma in:

 std::cout << " Hello World;" << std::endl; 

dovresti vedere solo uno.

Perché hai chiamato fork () senza svuotare prima tutti i buffer.

 cout.flush(); fork(); 

Il codice per l’output "Hello World" viene eseguito una sola volta. Il problema è che il buffer di output non viene scaricato. Quindi, quando si esegue il fork del processo, "Hello World" è ancora presente nel buffer di output. Quando entrambi i programmi escono, i loro buffer di output verranno svuotati e vedrai l’output due volte.

Il modo più semplice per dimostrarlo è aggiungere una nuova riga alla fine della stringa, che causerà uno svuotamento implicito, oppure eseguire il flush in modo esplicito con std::cout.flush(); . Quindi vedrai l’output solo una volta.

Se usi:

 std::cout << " Hello World" << std::flush; 

Ne vedi solo uno. Immagino che fork() copi tutto il buffer di output std::cout scrive.

La stringa non viene immediatamente scritta sullo schermo; invece, è scritto su un buffer interno. Il processo figlio eredita una copia del buffer di output, quindi quando il cout del bambino viene scaricato automaticamente, Hello World viene stampato sullo schermo. Il genitore stampa anche Hello World .

Se svuotate il cout prima della fork() , il problema quasi sicuramente scomparirà.

Il motivo è che quando invochi std::cout<< non esegue realmente l'output stesso ma i dati vengono lasciati in un buffer nel sistema. Quando si esegue il fork, vengono copiati sia il codice che i dati, nonché tutti i buffer associati. Infine, sia padre che figlio li svuotano sullo standard output e quindi si vede l'output duplicato.

Quello che probabilmente vedrai qui è un effetto del buffering. In generale, l’output viene memorizzato nel buffer fino a quando non viene esplicitamente svuotato o implicitamente eseguito con un’azione come l’output di una nuova riga. Poiché l’output è memorizzato nel buffer, entrambe le copie del processo biforcato hanno un output bufferizzato e quindi entrambe vengono visualizzate sul processo che termina e svuota il buffer