在Linux上使用C管道中的2个管道进行双向父子通信

时间:2012-02-16 19:54:04

标签: c linux process communication pipe

我正在尝试使用Linux上的C使用2个管道在父进程和子进程之间创建双向通信。父母是我的程序,孩子只是一个随机程序(比如“猫”)。

我尝试在父级中使用read()来读取子输出,但是它给了我错误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);
}

2 个答案:

答案 0 :(得分:2)

如果要将stdin和stdout重定向到管道,则需要使用dup2(2)系统调用。

dup2 (ChildRead, 0);
dup2 (ChildWrite, 1);

P.S。 我也发现错误的读/写管道方向。这是正确的方法

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

记住:pipe [0]是fd用于读取,pipe [1]是fd用于写入。

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

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

答案 1 :(得分:0)

如果您只是执行读/写会怎样?老实说,我不确定dup和cat是你想要的,

char buf[256];
int len;

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

而且,进一步思考,如果你知道你想要结束的fd,请使用dup2,而不是dup。了解你的API,人们!

而且,进一步思考,你可以用更普遍的方式来看看popen(3)调用的来源,它正是这样做的。