Я пытаюсь изучить программирование в UNIX и натолкнулся на вопрос, касающийся fork()
. Я понимаю, что fork()
создает идентичный процесс текущего запущенного процесса, но где он начинается? Например, если у меня есть код
int main (int argc, char **argv)
{
int retval;
printf ("This is most definitely the parent process\n");
fflush (stdout);
retval = fork ();
printf ("Which process printed this?\n");
return (EXIT_SUCCESS);
}
Вывод:
This is most definitely the parent process
Which process printed this?
Which process printed this?
Я думал, что fork () создает тот же процесс, поэтому я сначала подумал, что в этой программе вызов fork () будет рекурсивно вызываться вечно. Я предполагаю, что новый процесс, созданный из fork (), запускается после вызова fork ()?
Если я добавлю следующий код, чтобы различать родительский и дочерний процессы,
if (child_pid = fork ()) printf ("This is the parent, child pid is %d\n", child_pid);
else printf ("This is the child, pid is %d\n",getpid ());
после вызов fork (), где дочерний процесс начинает свое выполнение?
Фактическое разветвление fork
происходит внутри примитива fork()
.
Вы можете просто представить, что внутри кода fork
системный вызов фактически дублирует процесс и начинает их выполнение в той же точке с небольшим отличием:
fork
функция вернет идентификатор процесса дочернего процесса fork
вернет 0. Таким образом, вы знаете, где находитесь во время программирования, например
if (fork())
{
printf("Parent speaking\n");
// parent's tasks
}
else
{
printf("Child here\n");
// child's tasks
}
fork () скопирует процесс, который разветвлен в в состояние , в котором он находится в настоящее время . *
Трудно сказать, в какой строке кода дочерний процесс запускается, вам действительно нужно посмотреть на разобранную скомпилированную версию, чтобы понять. Но часто можно предположить, что он начинается после вызова fork, конечно, в вашем случае.
Он копирует все свои переменные, стек, все это (фактически это пространство в памяти) копируется побайтово. Единственное, что меняется, это идентификатор процесса **.
Если вы сделаете это:
int i = random_integer();
fork();
Дочерний процесс будет иметь то же значение для i
, что и его родитель.
*: В дочернем процессе возвращаемое значение fork () будет 0 вместо идентификатора процесса.
**: Кроме того, дочерний процесс не будет иметь родительских замков и использования ресурсов.
Дочерний процесс начинает выполнение сразу после вызова fork()
. Более конкретно, сразу после fork () вернул либо идентификатор дочернего процесса, либо 0.