Fork() и выход
У меня есть простая программа:
int main()
{
std::cout << " Hello World";
fork();
}
После выполнения программы мой вывод: Hello World Hello World
. Почему это происходит вместо одного Hello world
? Я предполагаю, что дочерний процесс повторяется за кулисами, а выходной буфер распределяется между процессами или чем-то рядом с этими строками, но является ли это случаем или что-то еще происходит?
Ответы
Ответ 1
Это не совсем то, что вы считали изначально. Выходной буфер не разделяется - при выполнении fork, оба процесса получают копию того же буфера. Таким образом, после того, как вы развили fork, оба процесса в конечном счете очищают буфер и печатают содержимое на экран отдельно.
Этот происходит только потому, что cout буферизируется IO. Если вы использовали cerr, который не буферизирован, вы должны видеть сообщение только один раз, pre-fork.
Ответ 2
стандартный вывод использует буферизованный IO. Когда вызывается fork()
, стандартный вывод не очищается, и буферизованный контент реплицируется в дочернем процессе. Эти буферы очищаются при выходе из процесса, в результате чего вы видите два выхода.
Если вы измените программу на:
std::cout << " Hello World;" << std::endl;
вы должны увидеть только один.
Ответ 3
Потому что вы вызвали fork(), не сбрасывая сначала все буферы.
cout.flush();
fork();
Ответ 4
Код для вывода "Hello World"
выполняется только один раз. Проблема в том, что выходной буфер не сбрасывается. Поэтому, когда вы форкируете процесс, "Hello World"
все еще сидит в выходном буфере. Когда обе программы выходят, их выходные буферы будут сброшены, и вы увидите результат дважды.
Самый простой способ продемонстрировать это - добавить новую строку в конце строки, которая вызовет неявный флеш или явно скроется с std::cout.flush();
. Затем вы увидите только один выход.
Ответ 5
Если вы используете:
std::cout << " Hello World" << std::flush;
Вы видите только один. Я думаю, fork()
копирует любой выходной буфер std::cout
, который записывает.
Ответ 6
Строка не сразу записывается на экран; вместо этого он записывается во внутренний буфер. Детский процесс наследует копию выходного буфера, поэтому, когда дочерний элемент cout
автоматически очищается, на экран выводится текст Hello World
. Родитель также печатает Hello World
.
Если вы сбросили cout
до fork()
, проблема почти наверняка исчезнет.
Ответ 7
Причина в том, что при вызове std::cout<<
он действительно не выполняет сам вывод, но данные остаются в буфере в системе. Когда вы делаете вилку, копируются как код, так и данные, а также все связанные буферы. Наконец, и отец, и сын смывают их до стандартного вывода, и, таким образом, вы видите, что результат дублируется.
Ответ 8
То, что вы, вероятно, видите здесь, - эффект буферизации. В общем случае вывод буферизуется до тех пор, пока он явно не будет очищен или неявно выполнен с действием, таким как вывод новой строки. Поскольку вывод буферизирован, оба экземпляра разветвленного процесса имеют буферный вывод и, следовательно, оба отображают его при завершении процесса и сбросе буфера