如何使用 wait(); 控制多个 child 进程的行为?

How do I control the behavior of multiple child process using wait();

我正在尝试创建一个程序,其中 parent 进程进行一些计算并将其发送到 child 进程,child 进程分叉另一个进程并执行一些更多计算并将其发送到 child2 进程以进行进一步处理。 我似乎不知道该怎么做。 我的输出全乱了,有时 child 2 在 child 1 之前运行。有时 child 1 最后完成。 我希望其他进程等待它们。

我认为代码应该是这样的

#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;

int main(int argc, char *argv[])
{
    int fd[6];
    pipe(fd);
    pipe(fd + 2);
    pipe(fd + 4);

    pid_t id = fork();
    if (id == -1)
        return 1;
    if (id == 0)
    {
        wait(NULL);
        pid_t id2 = fork();
        if (id2 == -1)
            return 2;
        if (id2 == 0)
        {
            wait(NULL);
            pid_t id3 = fork();
            if (id3 == -1)
                return 2;
            if (id3 == 0)
            {

                wait(NULL);
                cout << "Child 3" << endl;
                // Read data from pipe and display
            }
            else
            {
                cout << "Child 2" << endl;
                // Read Data from pipe and Display
                // Some Computation
                for (int i = 0; i < 10000; i++)
                {
                }

                // Send Data to Child 3 through pipe
                wait(NULL);
            }
        }
        else
        {
            cout << "Child 1" << endl;
            // Read Data from pipe

            // Some Computation
            for (int i = 0; i < 100000000; i++)
            {
            }

            // Send Data to Child 2 through pipe
            wait(NULL);
        }
    }
    else
    {
        cout << "Parent" << endl;
        // Some Computation
        for (int i = 0; i < 2000; i++)
        {
        }
        // Send Data to Child 1 through pipe
        wait(NULL);
    }
}

一旦同一进程组中的任何childwait就会调用returns ] 终止(因此包括任何 grandchildren)。

如果您想等待 特定的 进程,请改用 waitpid。您还应该检查退出代码和状态。

最后,您应该等待 child 退出 在通过管道与它进行交互之后,而不是之前,您不应该在启动 child.

#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;

void die(const char* msg) {
  perror(msg);
  exit(1);
}

int main(int argc, char* argv[]) {
  int fd[6];
  pipe(fd);
  pipe(fd + 2);
  pipe(fd + 4);

  pid_t id = fork();
  if (id == -1)
    die("fork");
  if (id == 0) {
    pid_t id2 = fork();
    if (id2 == -1)
      die("fork 2");
    if (id2 == 0) {
      pid_t id3 = fork();
      if (id3 == -1)
        die("fork 3");
      if (id3 == 0) {
        cout << "Child 3" << endl;
        // Read data from pipe and display
        // Done. Nothing to wait for - just exit child 3
        cout << "Child 3 exiting" << endl;
      } else {
        cout << "Child 2" << endl;
        // Read Data from pipe and Display
        // Some Computation
        // Send Data to Child 3 through pipe
        // Wait for child 3 to finish before exiting child 2
        if (waitpid(id3, NULL, 0) < 0)
          die("waitpid 3");
        cout << "Child 2 exiting" << endl;
      }
    } else {
      cout << "Child 1" << endl;
      // Read Data from pipe
      // Some Computation
      // Send Data to Child 2 through pipe
      // Wait for child 2 to finish before exiting child 1
      if (waitpid(id2, NULL, 0) < 0)
        die("waitpid 2");
      cout << "Child 1 exiting" << endl;
    }
  } else {
    cout << "Parent" << endl;
    // Some Computation
    // Send Data to Child 1 through pipe
    // Wait for child 1 to finish before exiting parent
    if (waitpid(id, NULL, 0) < 0)
      die("waitpid 1");
    cout << "Parent exiting" << endl;
  }
}

打印:

Parent
Child 1
Child 3
Child 2
Child 3 exiting
Child 2 exiting
Child 1 exiting
Parent exiting

注意 Child 1/2/3 是随机打印的——那是因为所有 children 运行 是并行的,这是完美的正常(我们希望进程 运行 并行,这是分叉的重点)。当 reading/writing 管道时将强制执行排序 - 从管道读取的 child 将等待数据到达。