在Linux上使用2个管道实现C语言中的双向父子进程通讯

4
我正在尝试在Linux上使用C语言和2个管道创建父子进程之间的双向通信。父进程是我的程序,而子进程只是一个随机程序(比如"cat")。
我尝试在父进程中使用read()读取子进程输出,但是它给我返回了errno 9,即坏文件描述符。
以下是我的代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#define Read            0
#define Write           1
#define ParentRead      read_pipe[1]
#define ParentWrite     write_pipe[0]
#define ChildRead       write_pipe[1]
#define ChildWrite      read_pipe[0]

int main()
{
    int data_processed;

    /** Pipe for reading for subprocess */
    int read_pipe[2];
    /** Pipe for writing to subprocess */
    int write_pipe[2];

    char buffer[100];
    memset(buffer, '\0', 100);

    if (pipe(read_pipe) == 0 && pipe(write_pipe) == 0)
    {
        pid_t pid = fork();
        if (pid == (pid_t)-1)
        {
            fprintf(stderr, "Fork failure");
            exit(EXIT_FAILURE);
        }
        else if (pid == (pid_t)0) //Child process
        {
            close(Read);
            close(Write);
            close(ParentRead);
            close(ParentWrite);
            dup(ChildRead);
            dup(ChildWrite);
            execlp("cat", (char*)NULL);
            exit(EXIT_FAILURE);
        }
        else { //Parent process
            close(ChildRead);
            close(ChildWrite);

            write(ParentWrite, "abc", 3);
            int r = read(ParentRead, buffer, 99);
            printf("%d %d", r, errno);
            puts(buffer);
        }
    }

    exit(EXIT_SUCCESS);
}

3
在进行I/O操作之前,需要打开管道(open the pipes)。 - Pete Wilson
(pipe(read_pipe) == 0 && pipe(write_pipe) == 0) 不就是打开管道的同样方法吗? - Jeff
2个回答

3
如果您想将标准输入和输出重定向到管道中,则需要使用dup2(2)系统调用。
dup2 (ChildRead, 0);
dup2 (ChildWrite, 1);

另外,我发现管道的读写方向有误。这是正确的方式:


#define ParentRead      read_pipe[0]
#define ParentWrite     write_pipe[1]
#define ChildRead       write_pipe[0]
#define ChildWrite      read_pipe[1]

记住:pipe[0]是读取的文件描述符,pipe[1]是写入的文件描述符。

还有一个错误,在execlp中。不要忘记将您发送到执行程序的第一个参数设置为程序的名称。

execlp("cat", "cat", (char*)NULL);

我将所有的dup()更改为dup2(),但仍然得到相同的结果。read()返回-1,错误码为9。 - Jeff
我怎么会如此粗心。我甚至在编写程序时进行了双重检查。现在虽然没有出现错误,但 read() 返回的是 0。 - Jeff
你确定吗?我尝试了这个代码,read() 返回3,就像它应该的一样。 - mikithskegg

0

如果只进行读/写操作会发生什么?说实话,我不确定dup和cat是否适用于此:

char buf[256];
int len;

len = read(ChildRead, 256);
write(ChildWrite, len);

而且,更进一步思考,如果您知道要到达的fd,请使用dup2而不是dup。了解您的API,人们!

而且,更进一步思考,您可以查看popen(3)调用的源代码,以更通用的方式执行此操作。


1
我正在使用猫作为一个例子。我还有另一个子程序想要调用。而且popen()不允许双向通信。 - Jeff
@Jeff:popen 正好可以做到这一点,你只需要将其扩展为两个管道而不是一个即可。 - tbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接