вилка () и выход


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

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

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

8 56

8 ответов:

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

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

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

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

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

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

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

cout.flush();
fork();

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

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

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

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

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

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

если ты упустишь cout до fork() проблема почти наверняка уйдет.

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

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