2

我很难弄清楚 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");
}

我这里有两个管道。两个子进程正在写入各自的管道,父进程必须同时读取它们。

作为测试,我在每个管道上写了一个小字符串。然后我尝试读入它们并防止用 select 阻塞。唯一打印出来的是偶数管中的字符串。它似乎仍在阻止。我感到很沮丧,因为我觉得我在手册页上遗漏了一些东西。有人可以告诉我我做错了什么吗?

4

2 回答 2

5

返回后select(),您的 0 个或多个文件描述符将处于“就绪”状态,您可以在不阻塞的情况下读取它们。但是如果你读到一个还没有准备好的,它仍然会阻塞。现在你正在阅读所有这些,因为 select() 只等到一个准备好,很可能另一个不会。

你需要做的是找出哪些已经准备好了,而且只能read()从他们那里得到。的返回值select()会告诉你有多少准备好了,你可以用ISSET()宏询问一个特定的是否准备好了。

于 2012-10-02T01:33:30.143 回答
1
  1. 你需要使用FD_ZERO()- 见select之前FD_SET
  2. 在选择之前设置超时值。这些值通过select
于 2012-10-02T01:22:52.240 回答