【问题标题】:select()-able timersselect()-able 计时器
【发布时间】:2011-01-20 15:37:36
【问题描述】:

select() 是一个很棒的系统调用。您可以打包任意数量的文件描述符、套接字描述符、管道等,并在输入可用时以同步方式获得通知。

有没有办法创建一个间隔/单次计时器并将其与 select() 一起使用?这将使我免于为 IO 和计时设置多个线程。

【问题讨论】:

  • 你能说明你想要什么样的计时器吗? select() 有标准的超时参数。
  • 定时器参数在select()内部使用。如果 select() 在超时之前没有得到任何挂起的读/写/错误,那么它将返回。我正在寻找的是一个将计时器转换为文件描述符并将其打包到 fd_set 中的命令。
  • select timeout 参数仅用于在没有其他事件的情况下超时,在此之上构建多个间隔计时器和一次性计时器是相当多的工作
  • 关于“您可以打包任意数量的文件描述符、套接字描述符、管道”……这有点不正确。当 fd 的值超过 1023 时,select 开始崩溃。请参阅 here... 我会考虑在类似 BSD 的系统上使用 kqueue,在基于 Linux 的系统上考虑 epoll,在基于 Windows 的系统上考虑重叠 IO系统。

标签: c linux select system-calls


【解决方案1】:

timerfd_create 正是这样做的。它是最近添加到 linux 内核中的一个,但可能尚未在所有发行版上都可用。

【讨论】:

  • 哇.. 我怎么不知道这件事?我必须复习一下我的 linux 系统调用。
  • 还有一个 signalfd 调用,以防您也希望将信号作为 fd 事件传递:-)
【解决方案2】:

使用 timeout 参数 - 将您的计时器事件保留在优先队列中,检查顶部项目并相应地设置超时 - 如果达到超时,那么您可以检查事件是否已准备好运行,运行事件并继续.

至少我是这样做的。

请注意,poll 具有更好的界面(在某些方面),并且在使用大量文件描述符时可能会更有效。

【讨论】:

  • +1 感谢马克。您是否有使用您建议的技巧的示例代码或 FOSS 的指针?
【解决方案3】:

MarkR 有一个不错的便携式解决方案,但这里有另一个:

使用 POSIX 计时器 (timer_create),您可以将问题转换为“select-able 信号”。这个问题有一个经典的解决方案:从信号处理程序写入管道,并在管道的读取端selecting。

【讨论】:

  • 哇,这正是我想要的。谢谢! :)
【解决方案4】:

以@MarkR 为基础,使用排序结构来存储回调+闭包,其中包含一个 int 和一个指向 int 的指针。如果两个 int 具有相同的值,则事件处于活动状态,否则将被丢弃。

这种方式可以简单地通过增加一个 int 来丢弃事件。也许不是最直接的解决方案,但这是我能想到的。

https://github.com/cheako/tor2web/tree/6ac67f80daaea01d14a5d07e6026e1af4258dc96/src

hextree.c contains the code for the data structure used.
schedule.c:156 is where the int is changed.
gnutls.c:197 is where the timers are created.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 2022-12-26
    • 2015-03-16
    • 1970-01-01
    • 2022-12-26
    • 2022-12-27
    • 1970-01-01
    相关资源
    最近更新 更多