C 计时器\u如何在第一个计时器过期后停止递归线程函数调用?
我用简单的“timer_create”创建了一个计时器。计时器是使用SIGEV_线程创建的。也就是说,当计时器过期时,会调用计时器线程函数 计时器的工作原理是,假设:C 计时器\u如何在第一个计时器过期后停止递归线程函数调用?,c,linux,timer,C,Linux,Timer,我用简单的“timer_create”创建了一个计时器。计时器是使用SIGEV_线程创建的。也就是说,当计时器过期时,会调用计时器线程函数 计时器的工作原理是,假设:expiry=3secs且计时器间隔为1ns,则计时器每1ns持续滴答一次,直到到期。一旦计时器过期,从该实例开始,每隔1ns(计时器间隔)它就会继续命中计时器线程函数。每次点击都会创建一个线程,直到计时器被删除。 我不希望这种情况发生,我希望一旦计时器过期,它应该只运行一次线程函数 我怎样才能做到这一点?我们可以在计时器中添加任何
expiry=3
secs且计时器间隔为1ns
,则计时器每1ns持续滴答一次,直到到期。一旦计时器过期,从该实例开始,每隔1ns(计时器间隔)它就会继续命中计时器线程函数。每次点击都会创建一个线程,直到计时器被删除。
我不希望这种情况发生,我希望一旦计时器过期,它应该只运行一次线程函数
我怎样才能做到这一点?我们可以在计时器中添加任何选项吗?如果没有其他计时器API
提前感谢大家我认为这是POSIX定时器的glibc实现中的一个实现缺陷。对于实时使用至关重要的
timer\u getOverload
函数肯定无法在glibc实现中工作,因为它从内核返回“当前”过期的溢出计数,但是当多个过期事件并行运行时,“当前”就没有意义了。资源耗尽和失效事件的丢弃也存在严重问题,这使得实现无法用于实时目的。例如,在nptl/sysdeps/unix/sysv/linux/timer\u routines.c
中:
struct thread_start_data *td = malloc (sizeof (*td));
/* There is not much we can do if the allocation fails. */
...
在的Linux手册页中,您可以看到forSIGEV\u THREAD
:
这里的实现可能性包括,每个计时器通知都可能导致创建一个新线程,或者创建一个线程来接收所有通知
后者是唯一能够提供正确的实时语义的选择,但出于某种原因,glibc没有选择它
以下是一个可能的解决方法:
选择一个实时信号,在创建任何线程之前阻止该信号,并将计时器设置为与SIGEV\u信号一起使用该信号。现在,创建一个线程来处理计时器,并循环sigwaitinfo
,然后在每次返回时调用处理函数。这实际上是glibc应该使用的SIGEV_线程
的一种可能实现(也是最正确的实现)
另一种可能性:POSIX中正好有一个与同步相关的、非系统调用的异步信号安全函数:sem\u post
。因此,为了传递计时器事件,可以使信号处理程序(而不是从sigwaitinfo
获取信号)与另一个线程同步。但我还没有弄清楚细节,看起来可能很难或不可能。只需将计时器间隔设置为0,到期时间设置为您想要的任何时间。您的计时器将过期一次(线程创建并运行),然后保持解除状态。这确实是glibc的一个严重实现缺陷。你的解决方案看起来不错,但我们不能使用信号。这是一个工具和设计要求。你还有其他选择吗?在设置计时器时,我们不能设置任何选项来指定线程数吗?不,没有这样的选项。另一种解决方法是忽略计时器,只需创建一个线程,该线程在给定的绝对时间之前反复休眠(需要使用绝对时间而不是相对时间来避免错误累积),并读取当前时间以手动计数溢出clock_nanosleep
具有此功能。使用1ns定时器,虽然你根本不会睡觉,但每次你能处理的过期时间至少会有5000-10000次超限。你确定吗?计时器仅启动和启用一次。一旦启动,我们就不能重新执行设置时间,否则它就会失败。计时器的工作方式是将到期时间倒计时到零,然后计时器触发,然后将间隔复制到到期时间,然后整个过程再次开始。所以,要做一次计时,这是我对你想要的东西的理解,将到期时间编程为你需要的时间,并将间隔设置为零。计时器将从到期计数到零,将触发一次,然后被禁用。此时,您应该能够使用settime重新编程。那是你想要的吗?