简体   繁体   English

在选择时阻止时将新FD添加到fd_Set

[英]Adding new FDs to fd_Set while blocking on select

I have a question regarding adding new socket file descriptors to an FDSET. 我有一个关于将新的套接字文件描述符添加到FDSET的问题。 Lets say we've already connected to a socket s1: 假设我们已经连接到插槽s1:

fd_set readfds;

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

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

and we are waiting for data to come down the socket, by calling select in a thread: 我们正在通过在线程中调用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
         .....
      }
   }

}

If I now wanted to add another socket (or may be two more socket etc) to the readfds set, given that select is blocking, how should I proceed? 如果我现在想在readfds集合中添加另一个套接字(或者可能是另外两个套接字,等等),考虑到select处于阻塞状态,我应该如何进行? how can I interrupt select 如何中断选择

Is the trick to add a zero timeout and use select like poll? 添加零超时并使用select like poll的技巧是吗?

You need to use the "pipe-trick". 您需要使用“管道技巧”。

This is where an additional socket or pipe is created add it to the fd_set. 在此处创建其他套接字或管道,将其添加到fd_set。

Then to interrupt a running or pending select, send a 1 byte message to it via another thread. 然后,要中断正在运行的或待处理的选择,请通过另一个线程向其发送一个1字节的消息。

The select will then return and if the special pipe FD is one of the ones that are ready in the set, that means you need to say look at a list or something "do work" - like add any new FDs to the fd_set before returning to the select call. 然后,选择将返回,并且如果特殊管道FD是集合中已准备好的管道之一,则意味着您需要说一下清单或“可做的事情”-像在返回之前将任何新FD添加到fd_set一样选择呼叫。

You can interrupt select by sending (and catching) a signal to your process, for example using raise . 您可以通过向进程发送(并捕获)信号来中断选择,例如使用raise select will return in this case with -1 and errno set to EINTR . 在这种情况下, select将返回,并且-1和errno设置为EINTR You can then change the events you want to wait for and call select again. 然后,您可以更改要等待的事件,然后再次调用select

Is the trick to add a zero timeout and use select like poll? 添加零超时并使用select like poll的技巧是吗?

One can simply use a timeout of 0 in which case it will just do a non-blocking check if any of the events got triggered, ie polling. 可以简单地将超时设为0在这种情况下,它将仅对是否触发了任何事件(即轮询)进行无阻塞检查。 But this should only be done in a few cases since busy polling instead of a blocking wait uses lots of resources of machine. 但这仅应在少数情况下完成,因为繁忙的轮询(而不是阻塞等待)会占用大量机器资源。 And I would even consider the interrupting of a blocking select a questionable design, although probably not as bad as busy polling. 我什至会考虑中断阻塞select一个有问题的设计,尽管可能不如繁忙的轮询那么糟糕。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM