Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 工作永无止境_C_Linux_Fork_Vfork - Fatal编程技术网

C 工作永无止境

C 工作永无止境,c,linux,fork,vfork,C,Linux,Fork,Vfork,下面的代码永远不会结束。为什么呢 #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;

下面的代码永远不会结束。为什么呢

#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;
}
#包括
#包括
#包括
#定义尺寸5
int nums[SIZE]={0,1,2,3,4};
int main()
{
int i;
pid_t pid;
pid=vfork();
如果(pid==0){/*子进程*/
对于(i=0;i0){/*父进程*/
等待(空);
对于(i=0;i
更新:

这段代码只是为了说明我对
vfork()
的一些困惑
,子进程不复制父进程的地址空间。相反,它共享地址空间。在这种情况下,我希望nums数组由两个进程更新,我的问题是按什么顺序?操作系统如何在这两个进程之间同步

至于为什么代码永远不会结束,可能是因为我没有任何明确用于退出的
\u exit()
exec()
语句。我说得对吗

更新2:
我刚刚读到: 我认为这篇文章帮助我解决了第一个困惑

vfork()系统调用中的子进程在父进程中执行 地址空间(这可能会覆盖父级的数据和堆栈) 挂起父进程,直到子进程退出


子对象必须退出而不是从主对象返回。如果子对象从主对象返回,则当父对象从主对象返回时,堆栈帧不存在:

如果vfork()创建的进程修改除用于存储vfork()返回值的pid类型变量以外的任何数据,则该行为未定义

在程序中,您修改的数据不是
pid
变量,这意味着行为未定义


您还必须调用以结束进程,或调用函数系列中的一个。

引用
vWork(2)
手册页:

vfork()函数与fork()具有相同的效果,不同的是,如果vfork()创建的进程修改用于存储vfork()返回值的pid类型变量以外的任何数据,或者从vfork()所在的函数返回值,则行为未定义已调用,或在成功调用_exit()或exec函数族之一之前调用任何其他函数


你正在做一大堆这样的事情,所以你不应该期望它能起作用。我认为这里真正的问题是:为什么要使用
vWork()
而不是
fork()

只需调用_exit,而不是调用return或insert _exit(0)到“子进程”的最后一行。返回0调用exit(0)关闭stdout时,当另一个printf出现时,程序崩溃。

不要使用
vfork
。这是你能得到的最简单的建议。
vfork
给你的唯一一件事就是挂起父进程,直到子进程调用
exec*
\u exit
。关于共享地址空间的部分是incorr例如,一些操作系统这样做,另一些选择不这样做,因为它非常不安全,并导致了严重的错误

上次我研究应用程序如何使用
vfork
时,事实上绝大多数应用程序都是错误的。糟糕的是,我扔掉了当时我正在使用的操作系统上启用地址空间共享的6个字符的更改。几乎所有使用
vfork
的人至少都会泄漏内存,甚至更糟

如果你真的想使用
vWork
,除了在子进程中返回后立即调用
\u exit
execve
之外,不要做任何事情。如果你想做其他事情,你就进入了未定义的领域。我真正的意思是“任何事情”。您开始解析字符串以为exec调用生成参数,并且您几乎可以保证某些内容会触及它不应该触及的内容。我还指的是
execve
,而不是来自exec系列的其他功能。许多libc都在
execvp
execl
execle
,等等中进行操作。在
vWork
环境中不安全

在您的示例中具体发生了什么:

如果您的操作系统共享地址空间,则从main返回的子项意味着您的环境将清理(自调用printf以来,刷新stdout、printf分配的空闲内存等)。这意味着调用的其他函数将覆盖父级被卡住的堆栈帧。
vWork
返回父级将返回到已被覆盖的堆栈帧,并且任何情况都可能发生,它甚至可能在堆栈上没有要返回的返回地址。您首先输入了未定义的行为计数通过调用printf,然后从main返回将您带入未定义的行为大陆,从main返回后的清理运行使您旅行到未定义的行为行星


intmain(void)
80年代是很久以前的事了。我想我倾向于同意
vWork
上的Linux手册:“很不幸,Linux从过去复活了这个幽灵”。鉴于
fork
是(在您可能使用的任何Linux版本中)作为一个轻量级操作,我不再担心
vWork
可能做什么或不做什么。您的假设中有一个错误。“相反,它共享地址空间。”这是不正确的。它可以共享地址空间,但不必共享。某些操作系统只实现挂起父级的
vWork
语义,但仍像普通
fork
一样复制地址空间。原因是共享地址空间会导致许多错误(我似乎记得某个系统调用mallo时的execvp