我使用简单的“timer_create”创建了一个计时器。使用SIGEV_THREAD创建计时器。也就是说,当计时器到期时,会调用计时器线程函数。
timer_create的工作原理是,假设:expiry=3
秒和timer interval is 1 ns
,然后定时器每隔1 ns保持一次滴答,直到到期为止。一旦定时器到期,从该实例开始,它每1 ns(定时器间隔)后继续按下定时器线程功能。并且每次点击都会继续创建一个帖子,直到删除计时器。
我不希望这种情况发生,我希望一旦计时器到期,它应该只执行一次线程函数。
我怎样才能做到这一点?我们可以在timer_create中添加任何选项吗?如果不是任何其他计时器API?
提前多多感谢
答案 0 :(得分:4)
我认为这是POSIX定时器的glibc实现中的一个实现缺陷。对于实时使用至关重要的timer_getoverrun
函数当然无法在glibc实现中工作,因为它从内核返回“当前”到期的溢出计数,但是当多个到期事件正在运行时与此同时,“当前”毫无意义。资源耗尽和丢失的到期事件也存在严重问题,这使得实现无法用于实时目的。例如,在nptl/sysdeps/unix/sysv/linux/timer_routines.c
:
struct thread_start_data *td = malloc (sizeof (*td));
/* There is not much we can do if the allocation fails. */
...
在sigevent
的Linux手册页中,您会看到SIGEV_THREAD
:
这里的实现可能性包括:每个计时器通知都可能导致创建新线程,或者创建单个线程来接收所有通知。
后者是唯一可以提供正确实时语义的选择,但出于某种原因,glibc没有采取这种选择。
以下是可能的解决方法:
选择实时信号,在创建任何线程之前阻止该信号,并设置计时器以使用SIGEV_SIGNAL
的信号。现在,创建一个用于处理计时器的线程,并在sigwaitinfo
上循环,然后在每次返回时调用处理函数。这实际上是glibc 应该使用的SIGEV_THREAD
的一种可能的实现(以及最正确的实现)。
另一种可能性:POSIX中只有一个与同步相关,非系统调用,异步信号安全的函数:sem_post
。因此,为了传递定时器事件,有可能使信号处理程序(与从sigwaitinfo
获取信号相反)与另一个线程同步。但我还没有弄清楚细节,似乎仍然很难或不可能。
答案 1 :(得分:1)
只需将计时器间隔设置为0并将到期时间设置为您想要的任何值。你的计时器将过期一次(并创建和运行线程),然后保持解除武装。