我很难弄清楚如何在UNIX中使用select()来管理管道。我已经多次扫描了手册页,但我并不完全理解给定的定义。
从阅读手册页,我的印象是select()会让系统等到所给出的文件描述符之一可以从管道中读取(在我的情况下)而不会阻塞。
这是我的一些大纲代码[编辑]:
int size, size2;
fd_set rfds;
struct timeval tv;
char buffer[100];
char buffer2[100];
int retval;
while(1)
{
FD_ZERO(&rfds);
FD_SET(fd[0], &rfds);
FD_SET(fd2[0], &rfds);
tv.tv_sec = 2;
tv.tv_usec = 0;
retval = select(2, &rfds, NULL, NULL, &tv); //2 seconds before timeout
if(retval == -1)
perror("Select failed.\n");
else if(retval)
{
size = read(fd[0], buffer, sizeof(buffer));
if(size > 0)
printf("Parent received from even: %s\n", buffer);
size2 = read(fd2[READ], buffer2, sizeof(buffer2));
if(size2 > 0)
printf("Parent received from odd: %s\n", buffer2);
}
else
printf("No data written to pipe in 2 last seconds.\n");
}
我这里有两个管道。两个子进程正在写入各自的管道,父进程必须在其中读取它们。
作为测试,我给每个管道写了一个小字符串。然后我尝试读取它们并防止使用select进行阻止。唯一打印出来的是偶数管道中的字符串。它似乎仍然是封锁的。我感到沮丧,因为我觉得我在手册页上遗漏了一些东西。有人能告诉我我做错了吗?
答案 0 :(得分:4)
select()
返回后,0个或多个文件描述符将处于“就绪”状态,您可以在其中无阻塞地读取它们。但如果你读了一个尚未准备好的,它仍会阻止。现在你正在阅读所有这些,因为select()只等到一个准备就绪,很可能另一个不会。
您需要做的是确定哪些已准备就绪,并且只有read()
来自它们。 select()
的返回值会告诉您有多少已准备就绪,您可以询问特定的一个是否已准备好使用ISSET()
宏。
答案 1 :(得分:1)
FD_ZERO()
- 请在FD_SET
select