在我的套接字编程作业中,我进行了如下所示的选择调用:
select(s+1, &rfds, (fd_set *)0, (fd_set *)0,&tv)
电视的类型为
struct timeval
我阅读了 select 的手册页,上面写着:
在Linux上,函数select修改超时以反映未睡眠的时间量;大多数其他实现不会这样做。当读取超时的 Linux 代码移植到其他操作系统时,以及当代码移植到在循环中重用 struct timeval 进行多个选择而不重新初始化它时,这都会导致问题。 select 返回后,请考虑超时未定义。
这是否意味着我的电视变量将在调用 select 后更改? (我使用的是Ubuntu)
是的,确实如此。为了可移植性,您应该在每次调用
select
之前重新初始化它。
变量仍将指向相同的结构,但结构的内容将已更改。
来自 POSIX:
成功完成后,select()函数可能会修改超时参数指向的对象。
没有要求这样做,因此可移植代码在
timeout
返回后不得依赖于 select
结构中的值,并且如果再次需要它们,则必须重置它们。参见:
http://www.opengroup.org/onlinepubs/9699919799/functions/select.html
另请注意,如果出现错误,当 select() 返回时,timeval 结构的内容未定义。由于您不能保证不会出现错误(EINTR 是最常见的),因此您需要一种机制来跟踪剩余时间(如果您关心的话),因此在返回后使用 timeval 结构的内容是浪费时间大多数情况下,即使没有便携性问题。
非常重要的注意事项:select() 会并不总是减少超时值。
一般来说,只要 select() 不立即返回,就会减少超时值。
当调用 select() 时,如果已经有数据在等待,尽管 select 调用需要一点时间来执行,超时并没有减少。
因此,在繁忙的系统上使用它作为时间度量是危险的。我们添加了一个解决方法,可以检测 select 何时运行并且超时值没有减少,并且在这种情况下会手动稍微减少它,以便超时仍会定期达到 0。