【问题标题】:vfork() system callvfork() 系统调用
【发布时间】:2011-05-20 12:09:25
【问题描述】:

我读到使用 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

有人可以解释一下为什么它实际上并没有停止并连续打印无限循环。

【问题讨论】:

  • 顺便说一句,vfork() 基本上已经过时了。它是从最新的 POSIX 标准中剥离出来的,并且具有现代的写时复制语义,即使有任何性能或内存节省,也不会为您带来什么好处。只需使用fork()。它速度非常快,适用于所有声称是 *nix-ish 的东西,并且对您可以做的事情没有任何限制。
  • 唯一仍然需要vfork 的时间是在wannabe-POSIX MMU-less 基于微控制器的垃圾上。

标签: c fork systems-programming


【解决方案1】:

您应该非常仔细地阅读vfork 的手册页:

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

(以上来自手册页的 POSIX 部分,因此(可能)适用于 Linux 以外的其他环境)。

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

【讨论】:

  • 是的,马特已经死了。它说_exit() 或 exec*() 并且它意味着它return只是一个简单的_exit() 调用,_exit() 不同于exit()
  • 确实,从main 返回可能会破坏父级的堆栈。这非常危险。我什至会说你根本不应该使用vfork。有充分的理由从 POSIX 中省略了它。
  • 如果我不能调用任何函数或修改变量,vfork 有什么意义?
  • @TheLogicGuy:您可以致电 exec 和朋友,这几乎是 AFAIK 的唯一用例。超级奇怪的功能,最好不要使用它。
猜你喜欢
  • 2012-03-10
  • 2013-08-19
  • 2014-12-25
  • 2016-02-09
  • 2014-06-15
  • 1970-01-01
  • 2021-11-08
  • 2014-09-22
  • 2015-06-02
相关资源
最近更新 更多