vfork永无止境 [英] vfork never ends

查看:99
本文介绍了vfork永无止境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码永无止境.这是为什么?

The following code never ends. Why is that?

#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数组都能被两个进程更新,我的问题是按什么顺序?操作系统如何在两者之间进行同步?

This code is just to illustrate some of the confusions I have regarding to vfork(). It seems like when I use vfork(), the child process doesn't copy the address space of the parent. Instead, it shares the address space. In that case, I would expect the nums array get updated by both of the processes, my question is in what order? How the OS synchronizes between the two?

至于为什么代码永无休止,可能是因为我没有明确的_exit()exec()语句用于退出.我说的对吗?

As for why the code never ends, it is probably because I don't have any _exit() or exec() statement explicitly for exit. Am I right?

UPDATE2:
我刚读过: 56. fork()和vfork()系统调用之间有何区别? 而且我认为这篇文章可以帮助我解决我的第一个困惑.

UPDATE2:
I just read: 56. Difference between the fork() and vfork() system call? and I think this article helps me with my first confusion.

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

The child process from vfork() system call executes in the parent’s address space (this can overwrite the parent’s data and stack ) which suspends the parent process until the child process exits.

推荐答案

请勿使用vfork.这是您可以获得的最简单的建议. vfork给您的唯一一件事就是暂停父级,直到子级调用exec*_exit.关于共享地址空间的部分是不正确的,有些操作系统会这样做,而另一些则选择不这样做,因为这非常不安全,并导致了严重的错误.

Don't use vfork. That's the simplest advice you can get. The only thing that vfork gives you is suspending the parent until the child either calls exec* or _exit. The part about sharing the address space is incorrect, some operating systems do it, other choose not to because it's very unsafe and has caused serious bugs.

上次,我查看了应用程序实际上是如何使用vfork的,绝对多数错误了.太糟糕了,我放弃了6个字符的更改,从而无法在当时使用的操作系统上共享地址空间.几乎所有使用vfork的人至少都会泄漏内存,即使情况更糟.

Last time I looked at how applications use vfork in reality the absolute majority did it wrong. It was so bad that I threw away the 6 character change that enabled address space sharing on the operating system I was working on at that time. Almost everyone who uses vfork at least leaks memory if not worse.

如果您真的想使用vfork,除了在子进程返回后立即调用_exitexecve之外,请勿执行其他任何操作.除此之外,您正在输入未定义的区域.我的意思是任何东西".您开始解析您的字符串以为exec调用做参数,并且可以保证有什么东西会碰到本不应该碰到的东西.我也指的是execve,而不是exec系列的其他功能.许多libc在execvpexeclexecle等中执行的操作在vfork上下文中是不安全的.

If you really want to use vfork, don't do anything other than immediately call _exit or execve after it returns in the child process. Anything else and you're entering undefined territory. And I really mean "anything". You start parsing your strings to make arguments for your exec call and you're pretty much guaranteed that something will touch something it's not supposed to touch. And I also mean execve, not some other function from the exec family. Many libc out there do things in execvp, execl, execle, etc. that are unsafe in a vfork context.

您的示例中发生的具体情况:

如果您的操作系统共享地址空间,则从main返回的孩子意味着您的环境正在清理环境(自从您调用printf以来刷新了stdout,由printf分配了可用内存等).这意味着调用了其他函数,这些函数将覆盖父级卡在其中的堆栈帧.在父级中返回vfork会返回已被覆盖的堆栈帧,并且任何事情都可能发生,它甚至可能没有返回地址.堆栈返回到了.您首先通过调用printf进入了未定义行为的国家,然后从main的返回将您带入了undefined行为大陆,并且在main的返回之后进行了清理,这使您进入了undefined behavior planet.

If your operating system shares address space the child returning from main means that your environment cleans things up (flush stdout since you called printf, free memory that was allocated by printf and such things). This means that there are other functions called that will overwrite the stack frame the parent was stuck in. vfork returning in the parent returns to a stack frame that has been overwritten and anything can happen, it might not even have a return address on the stack to return to anymore. You first entered undefined behavior country by calling printf, then the return from main brought you into undefined behavior continent and the cleanup run after the return from main made you travel to undefined behavior planet.

这篇关于vfork永无止境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆