2011-07-13 96 views
3

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

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() 
..... 
..... 

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

回答

4

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

另请注意,与fork不同,家长处于暂停状态,直到孩子退出或致电execve

+0

谢谢。将“return 0”替换为“exit(0)”后,程序按预期运行。我认为“回归”是无限循环的原因。 – deepsky

+0

是的,你正在用'return'破坏父级堆栈。 –

+1

@deepsky:不要调用'exit()',或者调用'_exit()' – JeremyP

1

从手动:

如果()由vfork的创建的流程修改从)比用于存储从vfork的(返回值的类型将为pid_t的变量之外的任何数据,或返回行为是未定义函数调用vfork(),或者在成功调用_exit()或其中一个exec系列函数之前调用任何其他函数。因为父母和孩子共享地址空间,所以你不能从调用vfork()的函数返回。 这样做可能会破坏父母的堆栈

0

在vfork孩子里面,你只能调用安全的函数来调用信号处理程序,所以从vfork里面的printf是一个非常糟糕的主意。