在 Linux C 中将两个进程的 stdout 重定向到另一个进程的 stdin [英] Redirect stdout of two processes to another process's stdin in Linux C

查看:72
本文介绍了在 Linux C 中将两个进程的 stdout 重定向到另一个进程的 stdin的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了多进程重定向标准输出的问题.

I'm running into problem about redirect stdout of multi process.

假设我有进程 A,我在 A 中使用 fork(),然后我得到了进程 A 和 B.我在 B 中使用 fork(),最后我得到了进程 A、B 和 C.B 和 C 都在执行exec() 的其他程序.

Assuming I have process A, I use fork() in A and then I get process A and B. And I use fork() in B, finally I get process A, B and C. Both B and C are implementing other program by exec().

现在,我尝试使用两个管道将 A 和 B 的标准输出重定向到 C 的标准输入.

Now, I try to redirect the stdout of A and B to stdin of C with two pipes.

#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(); ***/
        }
    }
}

现在,在这两个声明之后:

Now, after these two statements :

dup2(AtoC[0],STDIN_FILENO);
dup2(BtoC[0],STDIN_FILENO);

进程C的stdin最终被重定向到BtoC[0],也就是进程B的stdout,而进程A的stdout没有传入进程C的stdin.

the stdin of process C is finally redirect to BtoC[0] ,which is the stdout of process B. And the stdout of process A is not passed into process C's stdin.

我的问题是是否有任何解决方案可以让我同时将进程 A 和 B 的 stdout 重定向到进程 C 的 stdin.

My question is whether there is any solution can let me redirect both process A and B's stdout into process C's stdin at the same time.

另一个问题是如果我也想在屏幕上打印进程A的stdout,我该怎么办?我知道命令行中的命令 tee.我尝试在进程 A 中使用相应的函数 tee(int fd_in, int fd_out, size_t len, unsigned int flags),但我未能打印进程 A 的任何 stdout.

Another question is if I also want to print the stdout of process A in screen, what should I do? I know the command tee in command line. I try to use the corresponding function tee(int fd_in, int fd_out, size_t len, unsigned int flags)in process A, but I failed to print anything of stdout of process A.

感谢任何建议,谢谢.

推荐答案

我不确定这是一个好主意,但它完全可行.关键的观察是你只需要一个管道.多个进程(具有共同的父进程)可以写入单个管道.但是,只有一个文件描述符可以用作标准输入.在原始代码中,只有一个管道连接到 C 作为其标准输入(其他管道仍然连接,但主要是因为您没有关闭足够的描述符).

I'm not sure that it's a good idea, but it is perfectly feasible. The key observation is that you only need one pipe. Several processes (with a common parent) can write to a single pipe. However, only one file descriptor can be used as the standard input. In the original code, only one of the pipes was connected to C as its standard input (the others were still connected, but mainly because you hadn't closed enough descriptors).

  • 经验法则:如果您通过 dup2()(或 dup())将管道的一端连接到标准输入或标准输出,则应关闭两者pipe() 返回的文件描述符.
  • Rule of thumb: if you connect one end of a pipe to standard input or standard output via dup2() (or dup()), you should close both of the file descriptors returned by pipe().

试试这个代码的大小.我减少了树的灌木丛,删除了未使用的变量(没有使用 fork() 返回的进程 ID),重命名管道,确保它在每个进程中正确关闭,并提供了一些进程 A 和 B 中的写入活动以及进程 C 中的一些读取活动代替运行命令.我假设 usleep()(微睡眠,以微秒表示的睡眠时间)是可用的;如果没有,请尝试 nanosleep(),但它具有更复杂的界面.

Try this code for size. I've reduced the bushiness of the tree, removed unused variables (nothing uses the process IDs returned by fork()), renamed the pipe, made sure it is closed properly in each process, and provided some writing activity in processes A and B and some reading activity in process C in lieu of running commands. I'm assuming that usleep() (micro-sleep, sleep time expressed in microseconds) is available; if not, try nanosleep(), but it has a more complex interface).

#include <unistd.h>

int main(void)
{
    int ABtoC[2];
    pipe(ABtoC);

    if (fork() > 0)
    {
        // Process A
        close(ABtoC[0]);
        dup2(ABtoC[1], STDOUT_FILENO);
        close(ABtoC[1]);     // Close this too!
        // Process A writing to C
        for (int i = 0; i < 100; i++)
        {
            write(STDOUT_FILENO, "Hi\n", sizeof("Hi\n")-1);
            usleep(5000);
        }
    }
    else if (fork() > 0)
    {
        // Process B
        close(ABtoC[0]);
        dup2(ABtoC[1], STDOUT_FILENO);
        close(ABtoC[1]);
        // Process B writing to C
        for (int i = 0; i < 100; i++)
        {
            write(STDOUT_FILENO, "Lo\n", sizeof("Lo\n")-1);
            usleep(5000);
        }
    }
    else
    {
        char buffer[100];
        ssize_t nbytes;
        close(ABtoC[1]);
        dup2(ABtoC[0], STDIN_FILENO);
        close(ABtoC[0]);
        // Process C reading from both A and B
        while ((nbytes = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0)
            write(STDOUT_FILENO, buffer, nbytes);
    }
    return(0);
}

在我的 Mac(Mac OS X 10.7.5,GCC 4.7.1)上运行的最后结果:

The tail end of a run on my Mac (Mac OS X 10.7.5, GCC 4.7.1) produced:

Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Hi
Lo
Lo
Hi
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Lo
Hi

这篇关于在 Linux C 中将两个进程的 stdout 重定向到另一个进程的 stdin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆