Важным фоном здесь является то, что стандарт stdoutдолжен быть буферизован линией по умолчанию.
Это приводит \nк сбросу вывода.
Поскольку второй пример не содержит символ новой строки, выходные данные не сбрасываются и, поскольку fork()копирует весь процесс, он также копирует состояние stdoutбуфера.
Теперь эти fork()вызовы в вашем примере создают в общей сложности 8 процессов - все они с копией состояния stdoutбуфера.
По определению, все эти процессы вызывают exit()при возврате из, main()а затем exit()вызовы во всех активных потоках stdio . Это включает в себя, и в результате вы видите один и тот же контент восемь раз.fflush()fclose()stdout
Хорошей практикой является вызов fflush()всех потоков с ожидающим выводом перед вызовом fork()или явное разрешение разветвленного дочернего вызова, _exit()который только завершает процесс, не сбрасывая потоки stdio.
Обратите внимание, что вызов exec()не очищает буферы stdio, поэтому нормально не заботиться о буферах stdio, если вы (после вызова fork()) вызываете exec()и (если это не удается) вызываете _exit().
КСТАТИ: Чтобы понять, что неправильная буферизация может вызвать, вот старая ошибка в Linux, которая была недавно исправлена:
Стандарт требует stderrотмены stderrбуферизации по умолчанию, но Linux проигнорировал это и сделал буферизацию строки и (что еще хуже) полную буферизацию в случае, если stderr был перенаправлен через канал. Так что программы, написанные для UNIX, выводили вещи без перевода строки в Linux слишком поздно.
См. Комментарий ниже, кажется, сейчас исправлено.
Вот что я делаю, чтобы обойти эту проблему Linux:
/*
* Linux comes with a broken libc that makes "stderr" buffered even
* though POSIX requires "stderr" to be never "fully buffered".
* As a result, we would get garbled output once our fork()d child
* calls exit(). We work around the Linux bug by calling fflush()
* before fork()ing.
*/
fflush(stderr);
Этот код не наносит вреда на других платформах, так как вызов fflush()только что очищенного потока является пустым занятием.
./prog1 > prog1.out) или канал (./prog1 | cat). Приготовьтесь к тому, что ваш разум будет взорван :-)