我有两个管道,它们都在随机点获得不同的数据。我想要的是将两个管道中的内容打印到 stdout 。
__________________
pipe1 | |
]==============> -----------.
| | \
| process1 | -----> stdout
pipe2 | | /
]==============> -----------´
|__________________|
我的代码在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));
}
然而,这不起作用,因为当数据来自另一个管道时,可以阻止一个read()
(如果没有数据到来)。
如何从两个管道中同时打印同时而不会在一个管道中被阻止?或者关于如何解决这个问题的任何其他建议都是受欢迎的。
答案 0 :(得分:3)
使用select
在两个套接字上等待。数据准备就绪后,它会告诉您哪些管道有可用的数据。
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);
}
}
注意上面的内容会永远运行,除非出现错误。您可能希望程序在某个时刻停止。
答案 1 :(得分:2)
您需要多路复用输入。相关的系统调用是poll或select(或ppoll
或pselect
)。 select tutorial对于阅读非常有用。