0

fork() и вывод данных

9

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

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

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

5 ответ(ов)

0

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

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

0

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

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

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

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

0

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

cout.flush();
fork();

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

0

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

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

0

Действительно, когда вы используете std::cout << " Hello World" << std::flush;, это выводит строку на стандартный вывод и сбрасывает буфер. Однако, важно понять, что при вызове fork(), дочерний процесс наследует текущее состояние процессов, включая буферы, используемые для вывода.

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

Если оба процесса (родительский и дочерний) вызывают flush или другие операции вывода, они могут вывести данные в интерлевированном или непредсказуемом порядке. Поэтому да, при использовании fork(), вы можете иметь "двойной" эффект вывода, если у вас было что-то записано в буфер, который еще не был сброшен. Чтобы избежать путаницы, рекомендуется всегда правильно использовать flush или обрабатывать вывод, чтобы избежать нежелательных эффектов в дочернем процессе.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь