我正在尝试设置一个程序,该程序使用进程间通信在四个进程之间使用管道/execl进行通信。这是演示管道使用的家庭作业问题的一部分,但我有点难以理解(即流程树是如何生长的)。这些进程是我的系统上二进制文件的实例,因此使用了execl。为了简要概述我正在努力实现的目标,我想将stdin从整个父进程/程序重定向到一个名为"s"的子进程(这是我的系统上名为scan的二进制文件),它解释单词。在"s"/scan中,它处理来自stdin的单词,然后根据单词,将单词发送/写入一个进程("e")或另一进程("o")。e/o进程实际上是同一个二进制文件,只是有符号链接——它基本上做同样的事情。
我该如何构建我的呼叫/家长程序来构建它?我必须在这个主程序中创建所有进程,否则我只会在scan/"s"进程中创建两个子进程。我在下面写了一些代码,将主程序的stdin重定向到"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 parentn");
wait(&status);
printf("Donen");
}
问题中的两个错误是:
-
我想将stdin从整个父进程/程序重定向到子进程
-
我认为最好得到另外两个潜艇的PID除了"s"/scan进程之外,我还需要创建的进程并使用不同的pid作为参数调用相应的二进制文件
以下程序应满足您的要求,但错误检查除外。
#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;
}
您可以设置一个动态变量以传入当前进程的编号,并使用非阻塞IO读取将由父进程写入管道的值。
这意味着在分叉之后,流程应该执行以下操作:
- 回声处理关闭无用的管道
- 读取值的父级(如果失败,请将其设置为0)
- 父级将增加的值写入管道
- 子CCD_ 2分配给同一程序
那应该没问题。