vfork()系统调用

5

我了解到使用vfork()系统调用创建的新进程在父进程的地址空间中作为线程执行,直到子线程调用exit()或exec()系统调用前,父进程将被阻塞。因此,我编写了一个使用vfork()系统调用的程序。

#include <stdio.h>  
#include <unistd.h>

int main()  
 {  
      pid_t pid;  
      printf("Parent\n");  
      pid = vfork();  
      if(pid==0)  
      {  
          printf("Child\n");  
      }  
      return 0;  
  }

我得到的输出如下:
 Parent  
 Child  
 Parent  
 Child  
 Parent  
 Child  
 ....  
 ....  
 ....

我曾认为return语句必须在内部调用exit()系统调用,因此我只期望输出为。
Parent  
Child

有人能解释一下为什么这个程序不会停止,而是持续打印无限循环吗?

3
顺便提一下,“vfork()”基本上已经过时了。它已经从最新的 POSIX 标准中删除,并且使用现代的写时复制语义几乎不会带来性能或内存节省方面的好处。只需使用“fork()”即可。它速度足够快,适用于所有声称是*nix-ish的系统,并且不会对您可以做什么设置任何限制。 - Nicholas Knight
vfork 仅在想要 POSIX MMU-less 微控制器垃圾上使用。 - R.. GitHub STOP HELPING ICE
1个回答

5
你应该非常仔细地阅读 vfork 的手册页面:

与 fork(2) 函数相同,但 vfork() 函数的行为在创建进程后如果修改除用于存储从 vfork() 返回值的 pid_t 类型变量之外的任何数据、从调用 vfork() 的函数中返回或在成功调用 _exit(2) 或 exec(3) 函数族之一之前调用任何其他函数,则其行为未定义。

(上述内容来自 man 页面的 POSIX 部分,因此可能适用于其他环境而不仅仅是 Linux。)

你正在调用 printf 并从子进程返回,因此你的程序的行为是未定义的。


没错,Mat 说得对。它说的是 _exit() 或 exec*() 并且它就是这个意思。return 不仅仅是一个简单的 _exit() 调用,而 _exit()exit() 是不同的。 - Nicholas Knight
1
确实,从main返回可能会破坏父进程的堆栈。这非常危险。我甚至可以说你永远不应该使用vfork。它被从POSIX中省略有很好的理由。 - R.. GitHub STOP HELPING ICE
如果我不能调用任何函数或修改变量,vfork有什么意义? - TheLogicGuy
1
@TheLogicGuy:你可以调用exec和相关函数,这大概是我所知道的唯一用例。虽然这个函数非常奇怪,但最好不要使用它。 - Mat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接