标准流和vfork

时间:2012-04-05 21:11:11

标签: c linux fork stdio

我正在使用fork / vfork函数,有些东西让我感到困惑。在史蒂文斯的书中写道:

  

请注意,在图8.3中,我们调用_exit而不是exit。

     

正如我们在7.3节中所述,_exit不执行任何标准I / O缓冲区的刷新。如果我们调用exit,结果是不确定的。   根据标准I / O库的实现,我们可能会看到输出没有差异,或者我们可能会发现父printf的输出已经消失。   如果子调用exit,则实现会刷新标准I / O流。   如果这是库采取的唯一操作,那么如果子进程调用_exit,我们将看到与生成的输出没有区别。   但是,如果实现也关闭标准I / O流,则将清除表示标准输出的FILE对象的内存。   因为孩子正在借用父母的地址空间,所以当父母恢复并调用printf时,不会出现任何输出,printf将返回-1。   请注意,父级的STDOUT_FILENO仍然有效,因为子级获取父级文件描述符数组的副本(请参见图8.2)。   退出的大多数现代实现都不会打扰关闭流。   由于进程即将退出,内核将关闭进程中打开的所有文件描述符。   在库中关闭它们只会增加开销而没有任何好处。

所以我尝试测试我是否可以获得printf错误,在我的vfork手册中有:

  

刷新并关闭所有打开的stdio(3)流。删除tmpfile(3)创建的文件。

但是当我编译并执行这个程序时:

  #include<stdio.h>
  #include<stdlib.h>
  #include<unistd.h>
  #include<sys/types.h>
  #include<sys/wait.h>

  int main()
{
  int s;
  pid_t ret;
  if (vfork() == 0)
  {
      //abort();
      exit(6);
  }
  else
  {
      ret=wait(&s);
      printf("termination status to %d\n",s);
      if (WIFEXITED(s))
          printf("normalnie, status to %d\n",WEXITSTATUS(s));
  }
  return 0;
}

一切正常,我没有得到任何printf错误。那是为什么?

1 个答案:

答案 0 :(得分:3)

你引用的段落的结尾说:

  

退出的大多数现代实现都不会打扰关闭流。由于进程即将退出,内核将关闭进程中打开的所有文件描述符。在库中关闭它们只会增加开销而没有任何好处。

这很有可能发生了什么。您的操作系统实际上并不关闭流(但它可能会刷新它)。

重要的不是exit在这里所做的事情,它的基本概念。孩子正在共享父母的记忆和堆叠框架。这意味着孩子可以很容易地改变父母没想到的东西,这很容易导致父母在再次开始跑步时崩溃或行为不端。 vfork的手册页说明流程唯一可以做的就是调用exit()exec。实际上,孩子甚至不应该分配内存或修改任何变量。

要了解这一点的影响,请尝试将vfork调用放在函数内部,让子进程返回或修改一些变量,看看会发生什么。

相关问题