我遇到了关于多进程重定向stdout的问题 .
假设我有进程A,我在A中使用fork(),然后我得到进程A和B.然后我在B中使用fork(),最后我得到进程A,B和C.B和C都在实现其他程序EXEC() .
现在,我尝试用两个管道将A和B的stdout重定向到C的stdin .
#include<unistd.h>
#include<stdio.h>
#include<sty/types.h>
int main()
{
int AtoC [2];
pipe(AtoC);
int fd1,fd2;
fd1=fork();
if(fd1>0)
{
/***In process A, I do the following steps: ***/
close(AtoC[0]);
dup2(AtoC[1], STDOUT_FILENO);
/* program running in process A */
}
else
{
int BtoC [2];
pipe(BtoC);
fd2=fork();
if(fd2>0)
{
/***In process B, I do the following steps: ***/
close(AtoC[1]);
close(BtoC[0]);
dup2(BtoC[1], STDOUT_FILENO);
/*** execute another program in process B using execl(); ***/
}
else
{
/*** In process C, I do the following steps: ***/
close(AtoC[1]);
close(BtoC[1]);
dup2(AtoC[0],STDIN_FILENO);
dup2(BtoC[0],STDIN_FILENO);
/*** execute another different program in process C using execl(); ***/
}
}
}
现在,在这两个陈述之后:
dup2(AtoC[0],STDIN_FILENO);
dup2(BtoC[0],STDIN_FILENO);
进程C的stdin最终重定向到 BtoC[0]
,这是进程B的stdout . 进程A的stdout没有传递给进程C的stdin .
我的问题是,是否有任何解决方案可以让我同时将进程A和B的stdout重定向到进程C的stdin .
另一个问题是,如果我还想在屏幕上打印进程A的标准输出,我该怎么办?我在命令行中知道命令 tee
. 我尝试在进程A中使用相应的函数 tee(int fd_in, int fd_out, size_t len, unsigned int flags)
,但是我无法打印任何进程A的stdout .
任何建议表示赞赏,谢谢 .
4 回答
我认为这是一个好主意,但它完全可行 . 关键的观察是你只需要一根烟斗 . 多个进程(使用公共父进程)可以写入单个管道 . 但是,只能使用一个文件描述符作为标准输入 . 在原始代码中,只有一个管道连接到C作为其标准输入(其他管道仍然连接,但主要是因为您没有关闭足够的描述符) .
dup2()
(或dup()
)将管道的一端连接到标准输入或标准输出,则应关闭pipe()
返回的两个文件描述符 .试试这个代码的大小 . 我减少了树的粗糙度,删除了未使用的变量(没有使用
fork()
返回的进程ID),重命名管道,确保在每个进程中正确关闭,并在进程A和B中提供了一些写入活动在进程C中读取活动代替运行命令 . 我假设usleep()
(微睡眠,以微秒表示的睡眠时间)可用;如果没有,请尝试nanosleep()
,但它有一个更复杂的界面) .Mac上运行的尾端(Mac OS X 10.7.5,GCC 4.7.1)产生:
跟进管道共享,您可能想要签出is-it-safe-to-pipe-the-output-of-several-parallel-processes . 对于小写,没有问题,但对于大写,数据可以得到interleaved =)
我不知道它是如何工作的,也等待op的其他答案 . 但是,您也可以使用类似
epoll
的异步I / O.过程A不需要阻止过程B / C的输出 . 进程A数据可用时读取 .man
页面有一个很好的例子如何使用tee
,仅供您参考 .这不可能 . 关于管道的整个想法是它有两个结束 - 一个连接到你的进程,比如进程A,另一个属于另一个进程,比如C.如果其他进程想要创建另一个进程,它还必须有2个结尾,并且两个端部不可能在一个孔中结束 .
当你这样做:
第二行有效地覆盖了第一行 . dup2(oldfd,newfd)应该关闭newfd并使其与oldfd有效相同 . 所以,第一行插入它,但第二行插拔它并插入不同的东西 .