在 select 上阻塞时向 fd_Set 添加新的 FD

问题描述 投票:0回答:2

我有一个关于向 FDSET 添加新套接字文件描述符的问题。假设我们已经连接到套接字 s1:

fd_set readfds;

//s1 = socket(...);
//connect(s1, ...)...

FD_ZERO(&readfds);
FD_SET(s1, &readfds);

我们正在通过在线程中调用 select 来等待数据从套接字传过来:

socket_reader_thread() {

   for (;;)
   {
      int rv = select(n, &readfds, NULL, NULL, &tv);

      if (rv == -1) {
         perror("select"); // error occurred in select()
      }
      else if (rv == 0) {
         printf("Timeout occurred!  No data after 10.5 seconds.\n");
      }
      else {
         // one the descriptors have data
         .....
      }
   }

}

如果我现在想添加另一个套接字(或者可能是另外两个套接字等)到 readfds 集中,考虑到 select 是阻塞的,我应该如何继续?我怎样才能中断选择

添加零超时并使用像 poll 这样的 select 的技巧是吗?

c sockets networking posix-select
2个回答
4
投票

你需要使用“管道技巧”。

这是创建额外套接字或管道的地方,将其添加到 fd_set 中。

然后要中断正在运行或挂起的选择,请通过另一个线程向其发送 1 字节消息。

然后选择将返回,如果特殊管道 FD 是集合中已准备好的管道之一,这意味着您需要说查看列表或“执行工作”的内容 - 就像之前将任何新的 FD 添加到 fd_set 中一样返回到选择调用。


2
投票

您可以通过向进程发送(并捕获)信号来中断选择,例如使用 raise。在这种情况下,

select
将返回,并且 errno 设置为
-1
。然后,您可以更改要等待的事件并再次拨打
EINTR

添加零超时并使用像 poll 这样的 select 的技巧是吗?

可以简单地使用
select

的超时,在这种情况下,如果任何事件被触发,它只会进行非阻塞检查,即轮询。但这仅应在少数情况下完成,因为繁忙轮询而不是阻塞等待会占用大量计算机资源。我什至认为中断阻塞

0
是一个有问题的设计,尽管可能没有繁忙轮询那么糟糕。
    

© www.soinside.com 2019 - 2024. All rights reserved.