2

我想使用 select() 从其他服务器接收更新并定期发送消息。考虑以下设置:

while(1){ select(... timeout = 5 秒); // 一些其他代码}

如果我在t = 2秒时收到更新,则select()将返回并执行相应的语句。当下一个循环开始时,超时将再次设置为 5 秒。但是,它应该是5 - 2 = 3秒。有没有办法用正确的时间更新计时器?

我想在 select() 之前手动启动一个计时器,但是这个计时器可能与select()中使用的计时器不同步。并且会引起其他潜在的问题。

4

3 回答 3

3

根据select手册页

在 Linux 上,select()修改超时以反映未睡眠的时间量;大多数其他实现不这样做。(POSIX.1-2001 允许任何一种行为。)

因此,您只需简单地重用该timeout变量。仅当您真正超时时才重置其值。

正如警告所暗示的那样,依赖此行为会导致移植问题,因此如果您依赖此行为,请确保将其记录在案,以便在移植代码时完成正确的事情。

于 2013-04-24T01:04:12.323 回答
1

time()在调用之前记住一个变量,在返回时select()获取另一个变量,并且......在下一次迭代中使用 not ,但作为超时值。time()select()while(1)55 - difference_between_times

也许您想使用new_timeout = 5 - difference_between_times % 5,因此如果在返回后的操作select时间超过 5 秒......您仍然设置timeout5 秒间隔。

您可能不应该使用秒,而是更细化的时间单位。并考虑以上是否是您真正想要的行为(使用模数)。也许何时difference_between_times > 5,您应该等待 5 秒。随心所欲,但你明白了。

于 2013-04-24T00:50:43.367 回答
1

当您的应用程序变得更复杂时,您可能有多个具有不同超时间隔的计时器。我们的确是。这是我们如何处理它。

每个计时器都有一个计时器对象,time_t 是计时器到期的时间。我们将所有计时器存储在堆数据结构中,因此最快到期的计时器位于堆的根部。在执行 select() 之前,我们获取堆的根,并从计时器的到期时间中减去当前时间,并将该增量用作 select() 调用的超时时间。

Timer * t = heap->Root();
time_t now = time(0);
timeval tv;
tv.tv_sec = t->when - now;
tv.tv_usec = 0;
select( ... & tv );
于 2013-04-24T03:29:45.473 回答