fork () si ramifica più del previsto?


Risposte:


245

Il fork()primitivo allunga spesso l'immaginazione. Fino a quando non ne avrai un'idea, dovresti tracciare su carta quale sia ciascuna operazione e tenere conto del numero di processi. Non dimenticare che fork () crea una copia quasi perfetta del processo corrente. La differenza più significativa (per la maggior parte degli scopi) è che fork()il valore di ritorno differisce tra genitore e figlio. (Poiché questo codice ignora il valore restituito, non fa alcuna differenza.)

Quindi, all'inizio, c'è un processo. Ciò crea un secondo processo, entrambi i quali stampano un punto e un ciclo. Alla loro seconda iterazione, ognuno crea un'altra copia, quindi ci sono quattro processi che stampano un punto e quindi escono. Quindi possiamo facilmente tenere conto di sei punti, come ti aspetti.

Tuttavia, ciò printf()che fa veramente è bufferizzare il suo output. Quindi il primo punto da quando c'erano solo due processi non appare quando è scritto. Quei punti rimangono nel buffer, che è duplicato in fork (). Non è fino a quando il processo sta per terminare che appare il punto bufferizzato. Quattro processi stampano un punto bufferizzato, più il nuovo dà 8 punti.

Se si desidera evitare tale comportamento, chiamare fflush(stdout);dopo printf().


12
Grazie, non sapevo che il buffer si duplica con fork (). Spiega un comportamento così strano.
Nikolay Kovalenko,

1
Non dovrebbe dare 10 punti, non 8? Poiché i 4 figli di seconda generazione ereditano il punto bufferizzato, aggiungono i propri, quindi sciacquano all'uscita, stamperebbero un totale di 8 punti, ma poi i 2 processi di prima generazione avrebbero comunque un punto ciascuno tamponato e svuotano quelli all'uscita, per un totale di 10.
psusi,

12
@psusi Uno dei processi di seconda generazione è un processo di prima generazione. fork()non crea 2 quindi esce, crea solo 1 altro processo.
Izkata,

70

Sono presenti buffer non impegnati nei flussi di output . stdout è bufferizzato in linea e il buffer viene replicato insieme al resto del processo. Al termine del programma, il buffer senza commit viene scritto due volte (una volta per ogni processo). Entrambi utilizzano

printf("a\n");

e

printf("a "); fflush(stdout);

non mostrare il problema.

Nel tuo primo esempio, crei quattro processi che hanno ciascuno due punti nel buffer del flusso di output. Quando ogni flusso termina, scarica il suo buffer, generando otto punti.


2

quando i = 0

Process_1: testo bufferizzato = 1 punto

Process_2 (creato da Process_1): testo bufferizzato = 1 punto

quando i = 1

Process_3 (creato da Process_1): eredita 1 punto bufferizzato da Process_1 e stampa 1 punto da solo. In totale Process_3 stampa 2 punti.

Process_4 (creato da Process_2): eredita 1 punto bufferizzato da Process_2 e stampa 1 punto da solo. In totale Process_4 stampa 2 punti.

Process_1: stampa 2 punti (un punto bufferizzato quando i = 0 e un altro punto quando i = 1)

Process_2: stampa 2 punti (un punto bufferizzato quando i = 0 e un altro punto quando i = 1)

Uscita finale: 8 punti. :)

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.