我正在尝试学习 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() 调用之后,子进程从哪里开始执行?
答案1
新进程将在调用中创建fork()
,并将像父进程一样从它返回开始。返回值(您存储在 中retval
)fork()
将为:
- 0 在子进程中
- 父进程中子进程的PID
- 如果失败,则父级为 -1(自然没有子级)
您的测试代码工作正常;它存储来自fork()
in 的返回值child_pid
并用于if
检查它是否为 0(尽管它不检查错误)
答案2
我认为 fork() 创建了相同的进程,所以我最初认为在该程序中, fork() 调用将永远递归调用。我猜想从 fork() 创建的新进程是在 fork() 调用之后启动的?
是的。让我们对行进行编号:
int main (int argc, char **argv)
{
int retval; /* 1 */
printf ("This is most definitely the parent process\n"); /* 2 */
fflush (stdout); /* 3 */
retval = fork (); /* 4 */
printf ("Which process printed this?\n"); /* 5 */
return (EXIT_SUCCESS); /* 6 */
}
执行流程为:
caller process fork() → ...
↘
original program exec() → 2 → 3 → 4 → 5 → 6
↘
forked program 5 → 6
...这准确地解释了您收到的输出。
如果您想知道原始程序和分叉程序的行为可能有何不同,因为它们必然共享相同的代码,请参阅迈克尔·莫罗泽克的回答。
答案3
真正的解决办法是
switch (fork()) {
case -1 :
fprintf (stderr, "fork failed (%s)\n", strerror(errno));
break;
case 0 : // child process comes here
break;
default : // parent process
break;
}
// all continue here
答案4
无论 , 之后的代码都fork()
被复制到子进程中,并且不要混淆父进程和子进程,它们是两个不同的实体,具有相同的(重复的,不是共享的)环境。
现在看看你的输出...