我发现大部分服务器(例如RPG页游服务器)总是自己实现一个定时器,而不是使用系统定时器,例如在linux上,
int timerfd_create(int clockid, int flags)
你能告诉我为什么吗?我认为系统api(timerfd_create)可以有更高的性能。
阅读时间(7)。确实,timerfd_create(2) 很高效,但它是 Linux 特定的。
通过 timer_create(2) 等使用 Posix 计时器。可能更便携。
Linux 特定的
timerfd_create
(还有signalfd(2) & eventfd(2)...)的巨大优势是事件循环友好(因为它是一个文件描述符,例如管道)或插座)。然而,大多数事件循环都是构建在多路复用系统调用之上,例如 poll(2) ,它确实接受延迟(毫秒),或者较旧的 select(2)
没有理由不这样做。系统调用从 Linux 2.6.25 (2008) 开始才可用,库支持直到 glibc 2.8 (2009) 才出现。鉴于大多数人从教授或现有的开源项目中学习如何编写应用程序,到目前为止(2014 年)还缺乏实际示例。
timer_create()
生成的POSIX 计时器使用 sigevent 通知事件,该事件通过信号或类似线程的行为 (
SIGEV_THREAD
) 通知调用者。如果您想要同步事件循环,那么两者都会有问题,因为 a)在信号处理程序中无法做太多事情 b) 考虑到使用情况,线程间通信不必要地复杂。另一方面,timerfd 允许
epoll_wait
及其朋友(
poll
、
select
、...)同步处理计时器,就好像它是另一个传入连接一样。当然,这并不意味着您不应该使用 POSIX 计时器及其朋友来实现您自己的事件循环。如果可移植性是一个问题,或者您认为 POSIX 计时器更适合您的使用,请继续。
1)程序是一个维护大量打开连接的服务器。默认情况下,Linux 允许每个进程拥有 1024 个描述符。这可以改变,但是,事实仍然是文件描述符不是免费资源,如果您有数千个打开的套接字连接,您可能至少有那么多计时器来管理超时。所有这些加起来就有很多描述符。
2) 使用timerfds 的开销可能比在用户空间管理一组定时器的开销更大。阻塞对 select() 或更合适的 epoll_wait() 的调用涉及系统调用,而考虑到 Clock_gettime() 不需要这样的转换,可以在用户空间中管理一大组计时器,而无需任何此类转换。
http://linuxmogeb.blogspot.com/2013/10/how-does-clockgettime-work.html