fork () и вывод - PullRequest
       24

fork () и вывод

56 голосов
/ 20 февраля 2012

У меня есть простая программа:

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

После выполнения программы мой вывод: Hello World Hello World.Почему это происходит вместо одного Hello world?Я предполагаю, что дочерний процесс перезапускается за кулисами, и выходной буфер распределяется между процессами или что-то в том же духе, но так ли это, или что-то еще происходит?

Ответы [ 8 ]

93 голосов
/ 20 февраля 2012

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

Это происходит только потому, что cout буферизован IO .Если вы использовали cerr, который не буферизован, вы должны увидеть сообщение только один раз, pre-fork.

44 голосов
/ 20 февраля 2012

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

Если вы измените программу на:

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

, вы должны увидеть только один.

17 голосов
/ 20 февраля 2012

Потому что вы вызвали fork () без предварительной очистки всех буферов.

cout.flush();
fork();
10 голосов
/ 20 февраля 2012

Код для вывода "Hello World" выполняется только один раз. Проблема в том, что выходной буфер не очищен. Поэтому, когда вы разветвляете процесс, "Hello World" все еще находится в буфере вывода. Когда обе программы завершат работу, их выходные буферы будут сброшены, и вы увидите результат дважды.

Самый простой способ продемонстрировать это - добавить новую строку в конце вашей строки, что приведет к неявному сбросу или явному сбросу с std::cout.flush();. Тогда вы увидите только один раз.

9 голосов
/ 20 февраля 2012

Если вы используете:

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

Вы видите только одного. Я думаю, fork() копирует любой выходной буфер std::cout пишет в.

6 голосов
/ 20 февраля 2012

Строка не сразу записывается на экран; вместо этого он записывается во внутренний буфер. Дочерний процесс наследует копию выходного буфера, поэтому, когда дочерний cout автоматически очищается, Hello World выводится на экран. Родитель также печатает Hello World.

Если вы сбросите cout до fork(), проблема почти наверняка исчезнет.

3 голосов
/ 20 февраля 2012

Причина в том, что когда вы вызываете std::cout<<, он на самом деле не выполняет сам вывод, а данные остаются в буфере в системе.Когда вы выполняете форк, копируются и код, и данные, а также все связанные буферы.Наконец, и отец, и сын сбрасывают их на стандартный вывод, и, таким образом, вы видите дублированный вывод.

2 голосов
/ 20 февраля 2012

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

...