Подтвердить что ты не робот

Поведение системного вызова fork() в Linux в этом коде

Я читал в книгах и онлайн-ресурсах, что системный вызов fork() создает копию текущего процесса, и оба процесса запускаются из точки после вызова системного вызова fork(). Правильно ли это?

Если это правильно, то почему код ниже печатает "Test Test"? Он должен печатать "Тест" только один раз (по родительскому процессу).

#include <sys/types.h> /* pid_t */
#include <sys/wait.h>  /* waitpid */
#include <stdio.h>     /* printf, perror */
#include <stdlib.h>    /* exit */
#include <unistd.h>    /* _exit, fork */


int main(void)
{
    int ctr =1;
    int pc = 1;
    printf("%s", "Test ");
    pid_t pidmain = fork();
    return EXIT_SUCCESS;
}
4b9b3361

Ответ 1

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

Поскольку stdout буферизуется по умолчанию, он будет печатать сообщение только после того, как будут написаны символы новой строки или поток будет сброшен. Когда вы создаете новый процесс, текущий буфер записи (содержащий "Test" ) также будет дублироваться в новом процессе. Затем это будет напечатано после завершения процесса, поскольку это неявно закрывает (и flushes) stdout. Если вы замените printf("%s", "Test "); на printf("%s\n", "Test "); или добавите вызов fflush(stdout); до fork(), вы увидите ожидаемый результат.

Ответ 2

В тот момент, когда вы вызываете fork, оба процесса имеют строку "Test" в своих буферах для стандартного вывода. Когда каждый процесс завершает работу, они оба выравнивают этот текст до выхода (см. exit для объяснения). Вы могли бы (как было предложено) добавить новую строку в буфер (и это произойдет из-за буферизации - см. setbuf для объяснения). Или вы можете вызвать fflush (stdout) перед развилкой и получить именно то, что вы просили, - строку "Test".