在fork()之后,孩子将从哪里开始执行?


22

我正在尝试学习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);
}

输出为:

这绝对是父进程,
哪个进程打印了此文件?
哪个过程印出了这个?

我以为会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()调用之后,子进程将从哪里开始执行?


5
man fork肯定可以回答您的问题,顺便说一句
Alex

Answers:


23

新过程将在fork()调用内创建,并且将像父进程一样从新进程返回开始。的返回值(您存储在中retvalfork()将为:

  • 子进程中的0
  • 父进程中子进程的PID
  • 如果失败,则在父级中为-1(自然没有孩子)

您的测试代码可以正常工作;它存储来自fork()in 的返回值,child_pid并用于if检查返回值是否为0(尽管它不会检查错误)


13

我以为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

...准确解释了您收到的输出。

如果您想知道原始程序和分叉程序的行为方式可能不同,因为它们必须共享相同的代码,请参阅Michael Mrozek的答案。


请注意,1实际上不是指令。还要注意,原始程序和派生程序实际上并不能同时运行-任一程序都必须等待另一程序产生/被抢占。
badp

1
在多核/多CPU系统上,两个程序实际上可以同时运行。
jlliagre

@jilliagre多核系统实际上是关于多线程的。至于具有多个CPU的系统,我不知道实际情况是否如此我不是该领域的专家-似乎是一种不太可能的情况。如果我们同意OS可以同时运行多个进程(那么它将如何处理并发性?),那么当原始程序在CPU上运行指令4时,其他CPU可能总是忙于运行其他进程。
badp 2010年

我会说这是非常可能的情况,尤其是在第5步中发生底层系统调用和一些I / O的情况下,实际上不常见于使所有CPU繁忙,因为CPU很少是当前计算机的瓶颈。似乎您也混淆了多线程和多核。
jlliagre

8
我可以发表评论说那些斜箭头太棒了
JBirch 2010年

0

真正的解决方案是

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

-1

无论将后面的代码fork()复制到子进程中,并且不将父子进程混合在一起,它们都是两个不同的实体,它们具有相同的(重复的,非共享的)环境。

现在查看您的输出...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.