是否有任何乖巧的POSIX间隔计时器? [英] Are there any well-behaved POSIX interval timers?

查看:109
本文介绍了是否有任何乖巧的POSIX间隔计时器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由最后闰秒的启发

,我一直在探索使用POSIX调用时间(具体时间间隔定时器)。

POSIX提供了多种方法来设置定时器,但他们都是有问题的:


  • 睡眠了nanosleep - 这些都是烦人它们是由一个信号中断后重新启动,他们推出时钟偏差。可以避开一些,但不是全部,这歪斜一些额外的工作,但这些功能的使用实时时钟,所以这并不是没有缺陷。

  • setitimer函数或更现代的 timer_settime - 这些被设计为间隔计时器,但他们per-过程,这是一个问题,如果需要多个活动计时器。他们也不能同时使用,但是这是少了大事。

  • clock_gettime CLOCK_MONOTONIC使用时和 clock_nanosleep 看起来正确的答案 clock_nanosleep 支持绝对超时,所以你可以睡,增加超时,并重复。这很容易中断这种方式后,重新启动了。不幸的是,这些功能可能会成为Linux特有的:有在Mac OS X或者FreeBSD对他们没有支持

  • 那么pthread_cond_timedwait 可在Mac上,可以用 gettimeofday的工作作为一个缺憾解决办法,但在Mac它只能与实时时钟工作,所以它的主题时,系统时钟设置或闰秒发生的不当行为。

时有我丢失的API?是否有创建类UNIX系统乖巧间隔计时器一个合理的可移植的方法,或者这是否总结事物的状态今天?

这是规矩,合理移植,我的意思是:


  • 不容易出现时钟偏差(负,当然,系统​​时钟本身的偏差)

  • 弹性的系统时钟被设置或闰秒发生

  • 能支持多个计时器在同一进程

  • 可在至少在Linux,Mac OS X和FreeBSD

关于闰秒的说明(响应 - [R ..的答案

POSIX天正是86400秒长,但现实世界的日子很少能长或短。如何系统解决了这个矛盾是实现定义的,但它是常见的闰秒共享相同的UNIX时间戳为previous第二。另请参阅:闰秒以及如何与他们

Linux内核闰秒错误是未能设置时钟拨回一秒钟后,做家务的结果: HTTPS ://lkml.org/lkml/2012/7/1/203 。即使没有错误,时钟的将会的跃升向后一秒钟。


解决方案

POSIX计时器( timer_create )不需要信号;你也可以安排计时器终止在一个线程中通过 SIGEV_THREAD 的通知类型的交付。不幸的glibc的实现实际上会为每个过期一个新的线程(这两者有很大的开销,破坏实时质量稳健性的希望),尽管该标准允许每个到期同一线程的重用。

的短,我只想建议做自己的线程使用 clock_nanosleep TIMER_ABSTIME CLOCK_MONOTONIC 为间隔定时器。既然你提到了一些破碎的系统可能缺乏这些接口,你可以简单地有一个下拉的实施(基于例如关于那么pthread_cond_timedwait )在这样的系统,并计算其可能较低-quality由于缺乏单调时钟的,但是,这仅仅是使用低质量实行类似的MacOSX的一个基本的限制。

至于你对闰秒的关注,如果NTPD或相似的是使您的实时时钟向后跳的时候,一个闰秒发生,这是在NTPD一个严重的错误。 POSIX时间(因为纪元秒)是在每标准日历秒(一天的准确八万六千四百分之一),不是SI秒为单位,因此,唯一的地方跨越第二逻辑属于一POSIX系统(如果任何地方)处于当他们<$之间的转换 mktime / gmtime的 / 本地时间 C $ C> time_t的和分解时间。我一直没下袭击这一次的错误,但他们似乎是由于系统软件做了很多愚蠢的和错误的东西,而不是从任何根本性的问题。

Inspired by the last leap second, I've been exploring timing (specifically, interval timers) using POSIX calls.

POSIX provides several ways to set up timers, but they're all problematic:

  • sleep and nanosleep—these are annoying to restart after they're interrupted by a signal, and they introduce clock skew. You can avoid some, but not all, of this skew with some extra work, but these functions use the realtime clock, so this isn't without pitfalls.
  • setitimer or the more modern timer_settime—these are designed to be interval timers, but they're per-process, which is a problem if you need multiple active timers. They also can't be used synchronously, but that's less of a big deal.
  • clock_gettime and clock_nanosleep seem like the right answer when used with CLOCK_MONOTONIC. clock_nanosleep supports absolute timeouts, so you can just sleep, increment the timeout, and repeat. It's easy to restart after an interruption that way, too. Unfortunately, these functions might as well be Linux-specific: there's no support for them on Mac OS X or FreeBSD.
  • pthread_cond_timedwait is available on the Mac and can work with gettimeofday as a kludgy workaround, but on the Mac it can only work with the realtime clock, so it's subject to misbehavior when the system clock is set or a leap second happens.

Is there an API I'm missing? Is there a reasonably portable way to create well-behaved interval timers on UNIX-like systems, or does this sum up the state of things today?

By well-behaved and reasonably portable, I mean:

  • Not prone to clock skew (minus, of course, the system clock's own skew)
  • Resilient to the system clock being set or a leap second occurring
  • Able to support multiple timers in the same process
  • Available on at least Linux, Mac OS X, and FreeBSD

A note on leap seconds (in response to R..'s answer):

POSIX days are exactly 86,400 seconds long, but real-world days can rarely be longer or shorter. How the system resolves this discrepancy is implementation-defined, but it's common for the leap second to share the same UNIX timestamp as the previous second. See also: Leap Seconds and What To Do With Them.

The Linux kernel leap second bug was a result of failing to do housekeeping after setting the clock back a second: https://lkml.org/lkml/2012/7/1/203. Even without that bug, the clock would have jumped backwards one second.

解决方案

POSIX timers (timer_create) do not require signals; you can also arrange for the timer expiration to be delivered in a thread via the SIGEV_THREAD notification type. Unfortunately glibc's implementation actually creates a new thread for each expiration (which both has a lot of overhead and destroys any hope of realtime-quality robustness) despite the fact that the standard allows reuse of the same thread for each expiration.

Short of that, I would just recommend making your own thread that uses clock_nanosleep with TIMER_ABSTIME and CLOCK_MONOTONIC for an interval timer. Since you mentioned that some broken systems might lack these interfaces, you could simply have a drop-in implementation (based e.g. on pthread_cond_timedwait) on such systems, and figure it might be lower-quality due to lack of monotonic clock, but that this is just a fundamental limitation of using a low-quality implementation like MacOSX.

As for your concern about leap seconds, if ntpd or similar is making your realtime clock jump backwards when a leap second occurs, that's a serious bug in ntpd. POSIX time (seconds since the epoch) are in units of calendar seconds (exactly 1/86400 of a day) per the standard, not SI seconds, and thus the only place leap second logic belongs on a POSIX system (if anywhere) is in mktime/gmtime/localtime when they convert between time_t and broken-down time. I haven't been following the bugs that hit this time, but they seem to have resulted from system software doing a lot of stupid and wrong stuff, not from any fundamental issue.

这篇关于是否有任何乖巧的POSIX间隔计时器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆