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 точек вместо?

Ответ 1

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

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

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

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

Ответ 2

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

printf("a\n");

и

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

не обнаруживают проблемы.

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

Ответ 3

, когда я = 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 точек.:)