Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 计时器\u如何在第一个计时器过期后停止递归线程函数调用?_C_Linux_Timer - Fatal编程技术网

C 计时器\u如何在第一个计时器过期后停止递归线程函数调用?

C 计时器\u如何在第一个计时器过期后停止递归线程函数调用?,c,linux,timer,C,Linux,Timer,我用简单的“timer_create”创建了一个计时器。计时器是使用SIGEV_线程创建的。也就是说,当计时器过期时,会调用计时器线程函数 计时器的工作原理是,假设:expiry=3secs且计时器间隔为1ns,则计时器每1ns持续滴答一次,直到到期。一旦计时器过期,从该实例开始,每隔1ns(计时器间隔)它就会继续命中计时器线程函数。每次点击都会创建一个线程,直到计时器被删除。 我不希望这种情况发生,我希望一旦计时器过期,它应该只运行一次线程函数 我怎样才能做到这一点?我们可以在计时器中添加任何

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

计时器的工作原理是,假设:
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手册页中,您可以看到for
SIGEV\u THREAD

这里的实现可能性包括,每个计时器通知都可能导致创建一个新线程,或者创建一个线程来接收所有通知

后者是唯一能够提供正确的实时语义的选择,但出于某种原因,glibc没有选择它

以下是一个可能的解决方法:

选择一个实时信号,在创建任何线程之前阻止该信号,并将计时器设置为与
SIGEV\u信号一起使用该信号。现在,创建一个线程来处理计时器,并循环
sigwaitinfo
,然后在每次返回时调用处理函数。这实际上是glibc应该使用的
SIGEV_线程
的一种可能实现(也是最正确的实现)


另一种可能性:POSIX中正好有一个与同步相关的、非系统调用的异步信号安全函数:
sem\u post
。因此,为了传递计时器事件,可以使信号处理程序(而不是从
sigwaitinfo
获取信号)与另一个线程同步。但我还没有弄清楚细节,看起来可能很难或不可能。只需将计时器间隔设置为0,到期时间设置为您想要的任何时间。您的计时器将过期一次(线程创建并运行),然后保持解除状态。

这确实是glibc的一个严重实现缺陷。你的解决方案看起来不错,但我们不能使用信号。这是一个工具和设计要求。你还有其他选择吗?在设置计时器时,我们不能设置任何选项来指定线程数吗?不,没有这样的选项。另一种解决方法是忽略计时器,只需创建一个线程,该线程在给定的绝对时间之前反复休眠(需要使用绝对时间而不是相对时间来避免错误累积),并读取当前时间以手动计数溢出
clock_nanosleep
具有此功能。使用1ns定时器,虽然你根本不会睡觉,但每次你能处理的过期时间至少会有5000-10000次超限。你确定吗?计时器仅启动和启用一次。一旦启动,我们就不能重新执行设置时间,否则它就会失败。计时器的工作方式是将到期时间倒计时到零,然后计时器触发,然后将间隔复制到到期时间,然后整个过程再次开始。所以,要做一次计时,这是我对你想要的东西的理解,将到期时间编程为你需要的时间,并将间隔设置为零。计时器将从到期计数到零,将触发一次,然后被禁用。此时,您应该能够使用settime重新编程。那是你想要的吗?