Нужно знать, как работает форк? - PullRequest
6 голосов
/ 16 мая 2011

Я пытаюсь следующий код C:

int main()
{
    printf("text1\n");
    fork();
    printf("text2\n");
    return 0;
}

Я ожидал получить вывод, где я получаю два "text1" и два "text2", например:

text1
text1
text2
text2

Но вместо этого я получаю:

text1
text2
text2

только один "text1" ???Хорошо, если дочерний процесс выполняется из fork (), тогда почему я получаю два «text1» для следующего:

int main()  
{  
    printf("text1");  
    fork();  
    printf("text2\n");  
    return 0;  
}  

вывод теперь:

text1text2  
text1text2 

Если дочернийпроцесс начинается после разветвления, вывод должен быть:

text1  
text2  
text2  

Ответы [ 7 ]

24 голосов
/ 16 мая 2011

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


Для адресации вашего обновления, printf() буферизуется. Обычно буфер сбрасывается, когда в конце встречается символ новой строки '\n'. Однако, так как вы пропустили это, содержимое буфера остается и не очищается. В конце оба процесса (исходный и дочерний) будут иметь выходной буфер с "text1". Когда он в конечном итоге сбрасывается, вы увидите это в обоих процессах.

На практике вы должны всегда сбрасывать файлы и все буферы (включая stdout) перед разветвлением, чтобы этого не произошло.

printf("text1");
fflush(stdout);
fork();

Вывод должен выглядеть следующим образом (в некотором порядке):

text1text2
text2
7 голосов
/ 16 мая 2011

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

6 голосов
/ 16 мая 2011

fork клонирует текущий процесс.Новый процесс будет «запускаться» при вызове fork, а не при запуске main, как вы, вероятно, ожидаете.Таким образом, когда вы печатаете в первый раз, есть 1 процесс, затем, когда вы выполняете форк, есть два.

Поскольку после печати "text1" вы fork, он печатается только один раз.

Во втором примере дублированный вывод связан с буферизацией вывода - printf фактически не выводитчто-нибудь на экране, пока он не будет сброшен или не достигнет новой строки ('\n').

Следовательно, первый вызов printf фактически просто записывает данные в буфер где-то, затем данные копируются во второйадресное пространство процесса, а затем второй вызов printf очистил бы буфер, завершив "text1" в обоих буферах.

2 голосов
/ 16 мая 2011

Это потому, что fork ed процесс начинается после fork, а не с самого начала.exec запускает процесс с точки входа и печатает то, что вы ожидаете.

1 голос
/ 08 февраля 2014

Problem 1 : the output as
      text1
      text2
      text2

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

Problem 2 : the output as
      text1text2 
      text1text2 

Это все о буферизации. Перейдите по этой ссылке и узнайте об основах fork (). http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html
1 голос
/ 16 мая 2011

Дочерний процесс начнется с позиции fork (), поэтому вы получаете правильный вывод.

0 голосов
/ 16 мая 2011

из man 2 fork: fork возвращает 0 дочернему процессу.

value = fork();
if( value == -1 ) {
  printf( "fork failed\n" );
  exit(1);
}
if( value ) {
  printf( "test1\n" );
} else {
  printf( "test2\n" };
}
...