C - 如何使用带多个管道的select()?

时间:2012-10-02 01:15:09

标签: c select pipe

我很难弄清楚如何在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进行阻止。唯一打印出来的是偶数管道中的字符串。它似乎仍然是封锁的。我感到沮丧,因为我觉得我在手册页上遗漏了一些东西。有人能告诉我我做错了吗?

2 个答案:

答案 0 :(得分:4)

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

您需要做的是确定哪些已准备就绪,并且只有read()来自它们。 select()的返回值会告诉您有多少已准备就绪,您可以询问特定的一个是否已准备好使用ISSET()宏。

答案 1 :(得分:1)

  1. 您需要使用FD_ZERO() - 请在FD_SET
  2. 之前查看select
  3. 在选择之前设置超时值。这些值通过select
  4. 更改