vfork的永远不会结束(vfork never ends)

2019-08-07 23:42发布

下面的代码永远不会结束。 这是为什么?

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#define SIZE 5
int nums[SIZE] = {0, 1, 2, 3, 4};
int main()
{
  int i;
  pid_t pid;
  pid = vfork();
  if(pid == 0){  /* Child process */
    for(i = 0; i < SIZE; i++){
      nums[i] *= -i;
      printf(”CHILD: %d “, nums[i]);    /* LINE X */
    }
  }
  else if (pid > 0){  /* Parent process */
    wait(NULL);
    for(i = 0; i < SIZE; i++)
      printf(”PARENT: %d “, nums[i]);   /* LINE Y */
  }
  return 0;
}

更新:

该代码只是为了说明一些我有一个关于在混乱中vfork() 这似乎是,当我使用vfork()子进程不会复制父母的地址空间。 取而代之的是,这股地址空间。 在这种情况下,我预计NUMS阵列得到由两种处理的更新,我的问题是在什么样的顺序? 操作系统两者之间如何同步?

至于为什么代码永远不会结束,可能是因为我没有任何_exit()exec()语句明确了退出。 我对吗?

UPDATE2:
我刚才读: 叉()和vfork()系统调用56之间的差异? 我认为这篇文章可以帮助我与我的第一个困惑。

来自的vfork()系统调用的子进程的父进程的地址空间执行(这可以覆盖父的数据和堆栈),它暂停父进程,直到子进程退出。

Answer 1:

不要使用vfork 。 这是你可以得到最简单的建议。 那唯一vfork为您提供了将暂停家长直到孩子要么调用exec*_exit 。 有关共享地址空间的部分是不正确,有些操作系统做到这一点,其他不选择,因为它是非常不安全的,并已造成了严重的错误。

上次我看了应用程序如何使用vfork现实中的绝对多数没有错。 它是如此糟糕,我扔掉了6个字符的变化是启用的地址空间共享的操作系统我当时工作的。 几乎每个人都谁使用vfork至少出现内存泄漏如果不是更糟。

如果你真的想用vfork ,不这样做除了立即拨打任何_exitexecve它的子进程返回后。 还有什么你正在进入不确定的领土。 我真的是“什么”。 你开始解析你的字符串,使论据你exec调用,你都会有很大保证的东西会触动一些它不该碰。 我也意味着execve ,而不是从exec类的一些其他功能。 很多的libc在那里做的事情execvpexeclexecle ,等那是在一个不安全vfork上下文。

什么是具体发生在你例子:

如果您的操作系统共享地址空间中的孩子从main返回意味着你的环境清理的东西了(平标准输出,因为你叫printf的,这是由printf和这样的事情分配的内存)。 这意味着,还有其他的函数调用,将覆盖栈帧父被卡住英寸vfork在父返回到已被覆盖,任何事情都有可能发生堆栈帧返回,它甚至可能没有在堆栈上的返回地址返回了。 您首先通过调用printf的进入未定义行为的国家,然后从主回把你带到了未定义行为的大陆,并从主您前往未定义行为星球回归后作出清理运行。



Answer 2:

从引用vfork(2)手册页:

所述的vfork()函数具有作为叉),所不同的是,如果()或者通过vfork的创建的流程修改比用于存储从vfork的返回值的类型将为pid_t的变量之外的任何数据的行为是未定义相同的效果(,(),或从函数返回其中的vfork()被调用,或者调用任何其它函数之前成功调用_exit()或函数的EXEC家族的一员。

你做一大堆的那些东西,所以你不应该期望它的工作。 我觉得这里真正的问题是:为什么你使用vfork()而不是fork()



Answer 3:

从官方的规格 :

如果()由vfork的创建的流程修改比用于存储从vfork的返回值的类型将为pid_t的变量之外的任何数据(行为是未定义),

在你的程序修改比其他数据pid变量,这意味着该行为是不确定的。

您也可以致电_exit来结束进程,或致电之一exec系列函数。



Answer 4:

儿童必须_exit而不是返回main 。 如果孩子从返回main ,那么栈帧不父,当它从返回存在vfork



Answer 5:

只需调用_exit而不是调用返回或插入_exit(0)到“子进程”的最后一行。 返回0调用退出(0),而接近标准输出,另一个的printf如下这样的情况下,程序崩溃。



文章来源: vfork never ends
标签: c linux fork vfork