2012-06-21 3 views
182

Рассмотрим следующий фрагмент кода:fork() больше, чем ожидалось?

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 

int main(void) 
{ 
    int i; 
    for(i = 0; i < 2; i++) 
    { 
     fork(); 
     printf("."); 
    } 
    return 0; 
} 

Эта программа выводит 8 точек. Как это возможно? Разве не должно быть 6 точек?

+0

[Проверить это сообщение] (http://stackoverflow.com/questions/10909011/how-to-use-fork-to-create-only-2-child-processes/10909090#10909090) – tuxuday

+14

http: //ideone.com/B9HXL –

ответ

241

Первобытный примитив часто растягивает воображение. Пока вы не почувствуете это, вы должны проследить на бумаге, что такое каждая операция, и учитывать количество процессов. Не забывайте, что fork() создает почти идеальную копию текущего процесса. Наиболее значительная разница (для большинства целей) заключается в том, что возвращаемое значение fork() отличается между родительским и дочерним. (Так как этот код игнорирует возвращаемое значение, он не имеет значения.)

Итак, сначала есть один процесс. Это создает второй процесс, оба из которых печатают точку и петлю. На их второй итерации каждый создает другую копию, поэтому четыре процесса печатают точку, а затем выходят. Таким образом, мы можем легко учитывать шесть точек, как вы ожидаете.

Однако, что printf() действительно делает буфер его выход. Таким образом, первая точка, когда были только два процесса, не появляется при написании. Эти точки остаются в буфере —, который дублируется в fork(). Пока процесс не завершит выход из буферизованной точки. Четыре процесса печати буферизованной точки, плюс новый дает 8 точек.

Если вы хотите избежать этого поведения, позвоните по телефону fflush(stdout); после printf().

+12

Спасибо, я не знал, что буфер дублирует с fork(). Это объясняет такое странное поведение. –

+1

Должно ли это не давать 10 точек, а не 8? Поскольку дети из 4-х секундного поколения наследуют буферизованную точку, добавьте их собственные, а затем сбросьте их на выходе, они будут печатать в общей сложности 8 точек, но тогда у процессов второго поколения все еще будет одна точка, каждая из которых буферизуется, и сбросит их на выходе, давая в общей сложности 10. – psusi

+12

@psusi Одно из процессов второго поколения _is_ - процесс первого поколения. 'fork()' не создает 2, а затем выходит, он только создает еще 1 процесс. – Izkata

70

У вас есть незафиксированные буферы в выходных потоках. stdout буферизируется по строке, и буфер реплицируется вместе с остальной частью процесса. Когда программа завершается, незафиксированный буфер записывается дважды (один раз для каждого процесса). И с помощью

printf("a\n"); 

и

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

не проявляют проблему.

В первом примере вы создаете четыре процесса, каждый из которых имеет две точки в своем буфере выходного потока. Когда каждый поток завершается, он сбрасывает свой буфер, генерируя восемь точек.

2

, когда я = 0

Process_1: буферизацией текст = 1 точка

Process_2 (создатель Process_1): буферизацией текст = 1 точка

, когда г = 1

Process_3 (созданный Process_1): Наследует 1 буферизованную точку из Process_1 и печатает 1 точку отдельно. Всего Process_3 печатает 2 точки.

Process_4 (созданный Process_2): Наследует 1 буферизированную точку из Process_2 и печатает 1 точку отдельно. Всего Process_4 печатает 2 точки.

Process_1: печать 2 точка (одна буферном точки, когда я = 0, а другая точка, когда я = 1)

Process_2: печать 2 точки (одна буферном точки, когда я = 0, а другая точка, когда я = 1)

Конечный результат: 8 точек. :)

Смежные вопросы