从两个管道中读取数据,然后用C语言打印在标准输出上

从两个管道中读取数据,然后用C语言打印在标准输出上,c,pipe,stdout,C,Pipe,Stdout,我有两个管道,它们都在随机点获得不同的数据。我想要的是将内容从两个管道打印到标准输出 我的代码在process1中对此进行了说明: while (1) { read(pipe1[0], &buff, sizeof(char)); write(1, &buff, sizeof(char)); read(pipe2[0], &buff2, sizeof(char)); write(1, &buff2, sizeof(char)); } 但是,这

我有两个管道,它们都在随机点获得不同的数据。我想要的是将内容从两个管道打印到标准输出

我的代码在process1中对此进行了说明:

while (1) {
  read(pipe1[0], &buff, sizeof(char));  
  write(1, &buff, sizeof(char));
  read(pipe2[0], &buff2, sizeof(char)); 
  write(1, &buff2, sizeof(char));
}
但是,这不起作用,因为当数据来自另一条管道时,如果没有数据,则可以阻止一次读取

如何从两个管道同时打印而不被一个管道阻塞?或者关于如何解决此问题的任何其他建议都是受欢迎的。

用于在两个套接字上等待。当数据准备就绪时,它将告诉您哪些管道有可用的数据

void setnonblocking(int fd) {
    int opts;

    opts = fcntl(fd,F_GETFL);
    if (opts < 0) {
        perror("Couldn't get file descriptor flags");
        exit(EXIT_FAILURE);
    }
    opts = (opts | O_NONBLOCK);
    if (fcntl(fd,F_SETFL,opts) < 0) {
        perror("Couldn't set file descriptor to non-blocking");
        exit(EXIT_FAILURE);
    }
    return;
}

#ifndef BUFSIZE
#  define BUFSIZE 1024
#endif
void cat(fd_set* waiting, int fd) {
   static char buf[BUFSIZE];

   int readCnt;
   if (FD_ISSET(fd, waiting)) {
       while ((readCnt = read(fd, buf, BUFSIZE)) > 0) {
           write(stdout, buf, readCnt);
       }
       if (readCnt < 0) {
           perror("Error reading from pipe");
       }
   }
}

...
{
    fd_set pipes, readable;

    setnonblocking(pipes1[0]);
    setnonblocking(pipes2[0]);

    FD_ZERO(&pipes);
    FD_SET(pipe1[0],&pipes);
    FD_SET(pipe2[0],&pipes);

    int ready;
    while (1) {
        if ((ready = select(2, &pipes, NULL, NULL, NULL)) > 0) {
            cat(&pipes, pipe1[0]);
            cat(&pipes, pipe2[0]);
        } else {
            // no time limit, so there was an error
            perror("Error waiting for input");
            exit(EXIT_FAILURE);
        }
        FD_SET(pipe1[0],&pipes);
        FD_SET(pipe2[0],&pipes);
    }
}
请注意,除非出现错误,否则上述操作将永远运行。您可能希望程序在某个点停止。

用于在两个套接字上等待。当数据准备就绪时,它将告诉您哪些管道有可用的数据

void setnonblocking(int fd) {
    int opts;

    opts = fcntl(fd,F_GETFL);
    if (opts < 0) {
        perror("Couldn't get file descriptor flags");
        exit(EXIT_FAILURE);
    }
    opts = (opts | O_NONBLOCK);
    if (fcntl(fd,F_SETFL,opts) < 0) {
        perror("Couldn't set file descriptor to non-blocking");
        exit(EXIT_FAILURE);
    }
    return;
}

#ifndef BUFSIZE
#  define BUFSIZE 1024
#endif
void cat(fd_set* waiting, int fd) {
   static char buf[BUFSIZE];

   int readCnt;
   if (FD_ISSET(fd, waiting)) {
       while ((readCnt = read(fd, buf, BUFSIZE)) > 0) {
           write(stdout, buf, readCnt);
       }
       if (readCnt < 0) {
           perror("Error reading from pipe");
       }
   }
}

...
{
    fd_set pipes, readable;

    setnonblocking(pipes1[0]);
    setnonblocking(pipes2[0]);

    FD_ZERO(&pipes);
    FD_SET(pipe1[0],&pipes);
    FD_SET(pipe2[0],&pipes);

    int ready;
    while (1) {
        if ((ready = select(2, &pipes, NULL, NULL, NULL)) > 0) {
            cat(&pipes, pipe1[0]);
            cat(&pipes, pipe2[0]);
        } else {
            // no time limit, so there was an error
            perror("Error waiting for input");
            exit(EXIT_FAILURE);
        }
        FD_SET(pipe1[0],&pipes);
        FD_SET(pipe2[0],&pipes);
    }
}


请注意,除非出现错误,否则上述操作将永远运行。您可能希望程序在某个点停止。

您需要多路传输输入。相关系统调用为或ppoll或pselect。读取非常有用。

您需要多路传输输入。相关系统调用为或ppoll或pselect。读取时很有用。

一次读取和写入一个字符效率很低。根据C标准的§6.5.3.4-1,sizeofchar被保证为1。我看不出还有什么其他方法可以读取行而不是字符,因为长度将是可变的。读取数据块而不是行或字符。更新了我的答案,使之更加明确。一次读写一个字符效率低下。根据C标准的§6.5.3.4-1,sizeofchar被保证为1。我看不出还有什么其他方法可以读取行而不是字符,因为长度将是可变的。读取数据块而不是行或字符。更新了我的答案,使其更加明确。我认为没有必要将管道设置为非阻塞。您应该在每个管道上使用FD_ISSET宏来查看哪些管道有数据,只需点击那个按钮。@ams:将管道设置为非阻塞是防止读取调用被阻塞的必要条件。如果不不不必要地调用read,则不需要这样做-select的全部要点是它会告诉您哪个管道有数据。@ams:我不是指从没有等待数据的文件描述符中读取数据。很少有读取会阻塞的情况,即使没有不必要的读取。。。。用一个read调用来替换read循环将减少出现这种情况的可能性,但不会完全消除这种情况。我认为没有必要将管道设置为非阻塞。您应该在每个管道上使用FD_ISSET宏来查看哪些管道有数据,只需点击那个按钮。@ams:将管道设置为非阻塞是防止读取调用被阻塞的必要条件。如果不不不必要地调用read,则不需要这样做-select的全部要点是它会告诉您哪个管道有数据。@ams:我不是指从没有等待数据的文件描述符中读取数据。很少有读取会阻塞的情况,即使没有不必要的读取。。。。用一个read调用替换read循环将减少出现错误的可能性,但不会完全消除错误。