timer_create如何在第一个计时器到期后停止递归线程函数调用?

时间:2011-04-01 12:49:20

标签: c linux timer

我使用简单的“timer_create”创建了一个计时器。使用SIGEV_THREAD创建计时器。也就是说,当计时器到期时,会调用计时器线程函数。

timer_create的工作原理是,假设:expiry=3秒和timer interval is 1 ns,然后定时器每隔1 ns保持一次滴答,直到到期为止。一旦定时器到期,从该实例开始,它每1 ns(定时器间隔)后继续按下定时器线程功能。并且每次点击都会继续创建一个帖子,直到删除计时器。

我不希望这种情况发生,我希望一旦计时器到期,它应该只执行一次线程函数。

我怎样才能做到这一点?我们可以在timer_create中添加任何选项吗?如果不是任何其他计时器API?

提前多多感谢

2 个答案:

答案 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并将到期时间设置为您想要的任何值。你的计时器将过期一次(并创建和运行线程),然后保持解除武装。