【问题标题】:vfork never returnvfork 永不回归
【发布时间】:2011-07-13 08:54:20
【问题描述】:

为什么这个程序永远不会返回并继续创建子进程?

int main()
{
    pid_t pid;
    int foo1 = 1, foo2 = 2;
    printf("before fork()\n");

    if ((pid = vfork()) < 0 ) {
            printf("fork failed.\n");
    }else if (pid == 0) {
            foo1++;
            foo2++;
            printf("child process: pid is %d, my parent pid is  %d\n", getpid(), getppid());
    }else if (pid > 0){
            printf("parent process: pid is %d\n", getpid());
    }

    printf("%s: foo1 is %d, foo2 is %d\n",pid == 0 ? "child process" : "parent process", foo1, foo2);
    return 0;
}

输出是这样的:

before fork()
child process: pid is 17244, my parent pid is  15839
child process: foo1 is 2, foo2 is 3
parent process: pid is 15839
parent process: foo1 is -1079005816, foo2 is -1218256081
before fork()
child process: pid is 17245, my parent pid is  15839
child process: foo1 is 2, foo2 is 3
parent process: pid is 15839
parent process: foo1 is -1079005816, foo2 is -1218256081
before fork()
.....
.....

如果在第二个 if 块中添加一个 _exit 则可以。 我知道 vfork 与父进程共享相同的地址空间,但如果程序以崩溃而不是无限循环结束会更合理。

【问题讨论】:

    标签: c linux fork


    【解决方案1】:

    vfork 是一个非常棘手的系统调用,它的唯一用途是立即在子级中使用 execve - 对于其他类型的用途,它是危险且不可预测的。

    另请注意,与fork 不同,父级被挂起,直到子级退出或调用execve

    【讨论】:

    • 谢谢。将“return 0”替换为“exit(0)”后,程序按预期运行。我认为“返回”是死循环的原因。
    • 是的,您正在使用return 破坏父级堆栈。
    • @deepsky:也不要给孩子打电话exit(),打电话给_exit()
    • @deepsky:其实不要用vfork()
    • 谢谢大家。我只是好奇为什么这些会导致无限循环。真是巧合。
    【解决方案2】:

    来自手册:

    如果 vfork() 创建的进程修改了除用于存储 vfork() 返回值的 pid_t 类型变量以外的任何数据,或者从调用 vfork() 的函数返回,则行为未定义,或在成功调用 _exit() 或 exec 系列函数之一之前调用任何其他函数。

    因为父子共享地址空间,所以不能从调用vfork()的函数返回; 这样做会破坏父级的堆栈

    【讨论】:

      【解决方案3】:

      在 vfork 子进程中,您只能调用可安全调用信号处理程序的函数,因此 vfork 内部的 printf 是一个非常糟糕的主意。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-28
        • 2012-03-10
        • 1970-01-01
        • 2012-08-29
        • 2016-02-19
        • 2018-01-09
        • 2020-02-29
        相关资源
        最近更新 更多