2015-01-26 2 views
4

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

Однако в этом коде (ideone link):

int main() { 
    printf("%d: Common code1\n", getpid()); 
    if (fork() != 0) { 
    printf("%d: Parent code\n", getpid()); 
    } else { 
    printf("%d: Child code\n", getpid()); 
    } 
    printf("%d: Common code\n", getpid()); 
} 

Выход есть:

27380: Common code1 
27380: Parent code 
27380: Common code 
27380: Common code1 
27383: Child code 
27383: Common code 

Я не понимаю, почему четвёртая строка печатается? Я мог понять, был ли он напечатан из дочернего процесса и вилка main, но она напечатана от родителя, а fork не вызывает main.

+0

Возможный дубликат [Почему выход печатает дважды?] (Http://stackoverflow.com/questions/3822755/why-the-output-is-printing-twice) – leppie

+3

Вы действительно * имеете *, чтобы выбрать два чрезвычайно длинные строки, которые * отличаются только одним крошечным символом *? Вы ненавидите нас так много? –

+0

Чрезвычайно длинный? Я только что скопировал и вложил его, и добавив, что 1 была самой быстрой войной с дифференциацией –

ответ

8

Хороший вопрос! Сначала я немного смутился.

Когда вы используете printf, выход буферизуется. Это означает, что вещи, напечатанные printf, на самом деле не будут удалены на консоль до тех пор, пока не будет достигнута новая линия, или даже до тех пор, пока программа не завершится, если перенаправление stdout будет перенаправлено.

В этом случае. родительский буфер stdout PID копируется ребенку во время вилки. Затем, как родитель, так и ребенок записываются в свои буферы перед завершением. Это приводит к печати дублированных данных.

Here - это идеонная ссылка, которая включает в себя fflush(stdout); до fork().

+0

stdout не является «консольным блоком». Не связывайте tty с stdout, так как они разные. –

+0

Я не пытался объяснить магию за stdout; Я попытался объяснить наблюдаемый эффект как относящийся к вопросу и предложить решение. Спасибо за разъяснения! – millinon

2

Буферизация. Printf (обычно) ничего не пишет в stdout. Он просто обновляет некоторые внутренние структуры данных. Эти структуры данных дублируются в дочернем элементе, и когда поток сбрасывается, данные записываются. Вы должны flush(stdout) перед вами.

3

Проблема возникает из-за буферизации. Когда stdout не связан с терминалом, он не привязан к строке. Строки, которые вы пишете, достаточно коротки, чтобы оставаться внутри буфера и выписываются только после завершения программы. Таким образом, вы сначала видите процесс 27380, сбросив его буферы, а затем обработайте 27383, сбросив его буферы. Линия 27380: Common code1 не была вымыта перед вилкой, поэтому она находится в буфере как исходного, так и разветвленного процесса. Вызовите fflush() прямо перед разблокировкой, чтобы исправить эту проблему.

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