如何使用管道/excel最好地构建4个进程之间的进程间通信?

Posted

技术标签:

【中文标题】如何使用管道/excel最好地构建4个进程之间的进程间通信?【英文标题】:How to best structure inter-process communication bewteen 4 processes with pipes/execl? 【发布时间】:2012-02-25 03:21:49 【问题描述】:

我正在尝试设置一个程序,该程序使用进程间通信来使用管道/execl 在四个进程之间进行通信。这是演示管道使用的家庭作业问题的一部分,但我在理解它时遇到了一些困难(即进程树如何生长)。这些进程将成为我系统上二进制文件的实例,因此使用 execl。为了简要概述我要完成的工作,我想将标准输入从整个父进程/程序重定向到一个名为“s”的子进程(它是我系统上的一个名为 scan 的二进制文件),它解释单词.在“s”/scan 中,它处理来自其标准输入的单词,然后根据单词,然后将单词发送/写入到一个进程(“e”)或另一个进程(“o”)。 e/o 进程实际上是同一个二进制文件,只是有符号链接到它们——它基本上做同样的事情。

我将如何构建我的调用/父程序来构建它?我必须在这个主程序中创建所有进程,否则我只需在 scan/"s" 进程中创建两个子进程。我在下面有一些代码,我编写了将主程序的标准输入重定向到“s”进程,但我不确定在哪里分叉将连接到它的两个子进程。我认为最好获取除“s”/scan 进程之外我需要创建的其他两个子进程的 pid,并使用不同的 pid 作为参数调用相应的二进制文件,但我不确定。任何帮助将不胜感激!

 int s_to_e[2]; int s_to_o[2];
 int e_to_s[2]; int o_to_e[2];
 pid_t e_pid; pid_t o_pid; pid_t s_pid;

 if (pipe(s_to_e))           
      exit(1);
 

 if (pipe(s_to_o))           
      exit(1);
 

 if ( (s_pid = fork()) == -1) 
      fprintf(stderr, "Fork error! \n");
      exit(1);
 

 int status;

 //Child progress of scan
 if (s_pid == 0) 
      //Redirect stdin to s
      //This probably isn't the best way to go about doing this
      dup2(0, s_to_e[0]);
      close(s_to_e[1]);

      //We need to replace the child fork with a new process
      if(execl("./scan", "./scan", NULL ) == -1) 
           printf("execl Error!");
           exit(1);
      

  else 
      printf("I am parent\n");
      wait(&status);
      printf("Done\n");
   

【问题讨论】:

【参考方案1】:

您的问题中有两个错误:

我想将标准输入从整个父进程/程序重定向到子进程

父级的标准输入由子级继承,不会被重定向。

我认为最好获取其他两个子的 pid 除了“s”/scan 进程之外我还需要创建的进程 并以不同的 pid 作为参数调用各自的二进制文件

无需将自己的 id 传递给进程;它始终可以通过getpid() 获得。

以下程序应满足您的要求,但错误检查除外。

#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

main()

    int s_to_o[2];  pipe2(s_to_o, O_CLOEXEC);
    int s_to_e[2];  pipe2(s_to_e, O_CLOEXEC);
    if (fork() == 0)
     dup2(s_to_o[1], 1),
     dup2(s_to_e[1], 2), exit(execl("scan", "scan", NULL));
    close(s_to_o[1]);
    close(s_to_e[1]);
    if (fork() == 0)
     dup2(s_to_o[0], 0), exit(execl("o", "o", NULL));
    close(s_to_o[0]);
    if (fork() == 0)
     dup2(s_to_e[0], 0), exit(execl("e", "e", NULL));
    close(s_to_e[0]);
    wait(NULL);
    return 0;

【讨论】:

【参考方案2】:

您可以设置一个动态变量来传递当前进程的编号,并使用非阻塞 IO 读取将由父级写入管道的值。

意思是fork之后,进程应该做这些:

    echo 进程关闭无用的管道。 父级读取值(如果失败,将其设置为 0)。 父级将增加的值写入管道。 子 execl 到同一个程序。

那应该没问题。

【讨论】:

以上是关于如何使用管道/excel最好地构建4个进程之间的进程间通信?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中使用管道构建聊天程序

AppDomains之间如何最好地进行通信?

unix 管道是不是仅限于在 2 个进程之间使用?

如何使用 Asyncio 在 3 个子进程(使用管道)之间流式处理数据并使用结果数据

如何使用 Unix(或 Windows)中的(最好是未命名的)管道将一个进程的标准输出发送到多个进程?

C - 在顶层和底层进程之间进行通信