【问题标题】:How to properly fork() a process如何正确地 fork() 一个进程
【发布时间】:2014-11-14 22:00:00
【问题描述】:

我试图了解如何正确使用fork()execvp() 来执行命令。到目前为止,我有以下代码:

当我运行./test vim myFile.c 时,它会正确打开myFile.c,但我的行为很奇怪。似乎有两个进程正在运行,因为每当我输入任何内容时,它似乎都会发生两次。这是为什么呢?

int main (int argc, char* argv[]) {
   int fdin, pid, w, status; 
   fdin = 0;                                                                   
   if ((pid = fork()) < 0)                                                     
       errorExit (EXIT_FAILURE);                                                                                                                              
   execvp(argv[0],argv);  

   do {
      w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
      if (w == -1) {
          perror("waitpid");
          exit(EXIT_FAILURE);
      }

     if (WIFEXITED(status)) {
          printf("exited, status=%d\n", WEXITSTATUS(status));
      } else if (WIFSIGNALED(status)) {
          printf("killed by signal %d\n", WTERMSIG(status));
      } else if (WIFSTOPPED(status)) {
          printf("stopped by signal %d\n", WSTOPSIG(status));
      } else if (WIFCONTINUED(status)) {
          printf("continued\n");
      }
  } while (!WIFEXITED(status) && !WIFSIGNALED(status))
}

【问题讨论】:

  • execvp(argv[0], argv) 应该一遍又一遍地继续执行同一个程序(test,而不是vim!),因为您为fork() 的父级和子级调用它。 .
  • 在 fork() 之后,代码需要区分父子节点。您的代码没有区别,因此父母和孩子都在运行代码。所以父母和孩子都在执行 execvp() 函数。要区分,请检查返回的 pid 值,如果 ==0 则在子级中,否则在父级中。让父级(pid not - 0)跳过 execvp 调用

标签: c fork execvp


【解决方案1】:

当你调用 fork() 时,你创建了两个几乎完全相同的进程,父进程和子进程。这两个进程唯一的区别就是fork()的返回值,它返回0给子进程,子进程的pid返回给父进程。

因此,假设 fork 成功,fork 将在第 4 行向父进程和子进程返回一个非负整数。然后,父进程和子进程都将执行第 6 行,即 execvp,因此,您最终会得到两个运行您的 vim myFile.c 的不同进程,导致您描述的所有问题。

标准的成语是这样的:

if ((pid = fork()) < 0) {
    // Handle fork error
}
else if (pid == 0) {
    // Child process
    execvp(...);
}
else {
    // Parent process
    w = waitpid(pid, ...);
}

由于fork对于child的返回值为0,所以fork成功后,对于child的测试(pid == 0)为true,所以会调用execvp。

对于父进程,fork返回的是子进程的pid,所以仍然执行的检查(pid == 0)为假,所以执行else条件,导致父进程等待子进程。

【讨论】:

  • 我需要 do while 循环吗?
  • 不,您不需要 while 循环。默认情况下,waitpid 会导致父进程休眠,直到子进程退出。例如,请参阅linux.die.net/man/2/waitpid
  • 如果您滚动到手册页的底部,您会看到他们的示例代码包含一个 while 循环。这是为什么呢?
【解决方案2】:

你的程序中的父母和孩子都得到execvp()

if ((pid = fork()) < 0)
    errorExit (EXIT_FAILURE);
execvp(argv[0],argv);

您应该检查,如果您是 pid != 0 的父母,如果您是孩子,则不然。

【讨论】:

  • 我需要 do while 循环吗?
【解决方案3】:

你应该看看 fork 的返回值,在一个成功的 fork 之后你会在你的程序的相同位置有两个正在运行的进程。子进程将得到一个返回值 0,父进程将得到一个返回值,即子进程的 pid。您很可能希望在子进程和父进程中做不同的事情。

您可能还想再次考虑如何调用 execvp。您真的想将“./test”作为 execvp 的第一个参数吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 2012-01-12
    相关资源
    最近更新 更多