我很难弄清楚 select() 是如何处理 UNIX 中的管道的。我已经多次扫描手册页,但我并不完全理解给定的定义。
通过阅读手册页,我的印象是 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");
}
Run Code Online (Sandbox Code Playgroud)
我这里有两根管子。两个子进程正在写入各自的管道,父进程必须同时读取它们。
作为测试,我在每个管道上写了一个小字符串。然后我尝试读入它们并防止使用 select 阻塞。唯一被打印出来的是偶数管道中的字符串。它似乎仍在阻止。我感到很沮丧,因为我觉得我在手册页上遗漏了一些东西。有人能告诉我我做错了什么吗?
之后select()的回报,0个或更多的文件描述符将处于“就绪”状态,您可以在不阻塞读。但是如果你读到一个没有准备好的,它仍然会阻塞。现在您正在阅读所有这些,并且因为 select() 只等到一个准备好,另一个很可能不会。
你需要做的是弄清楚哪些已经准备好了,而且只能read()从他们那里。的返回值select()会告诉你有多少准备好了,你可以用ISSET()宏询问特定的是否准备好了。