不使用信号回调的Linux周期C定时器



需求很简单-实现一个C周期性计时器,它可以每隔x秒触发一次,并且每次计时器到期时都应该调用计时器回调函数。似乎一个足够简单的问题,我已经浏览了网页,但我正在寻找的例子,要么有FD和轮询参与,或定时器回调是使用信号处理程序实现。我想避免这两种情况。你能分享一些代码示例吗

https://man7.org/linux/man-pages/man2/timer_create.2.html -使用信号,这不是我感兴趣的,因为在我的进程中,可能有其他原因这个信号可以被调用,我如何在sig处理程序中区分,这个信号是我的定时器,而不是其他事件?

如何在sig处理程序中区分该信号是针对我的计时器而不是其他事件的?

查看从timer_create(2)链接的sigevent(7)手册页。传递给timer_createstruct sigevent中的一个成员是union sigval sigev_value。这个联合在手册页中没有定义,但是POSIX解释说它只是

union sigval {
int    sival_int;  // integer signal value
void*  sival_ptr;  // pointer signal value
};

您在这里设置的任何内容都将作为siginfo_t *第二个参数的si_value成员传递给您的信号处理程序,前提是您在调用sigaction时使用SA_SIGINFO。你只需要在这里使用不同的值当你设置定时器对应于不同的回调。您可以使用sival_int作为您自己选择的整数ID,唯一地标识这个特定的计时器,或者使用sival_ptr作为指向函数的指针或一些更复杂的数据结构,告诉您如何处理计时器刻度。然后你的信号处理程序只需要检查这个参数并分派到它指定的回调。

您还可以考虑timer_createSIGEV_THREAD模式,它使用处理程序触发一个新线程,而不是引发信号。所以,如果你想让你的回调在它自己的线程中运行,这可能是一个更简单的方法,因为你不需要信号处理程序作为调度程序。

但是如果你不想要额外的线程,我认为没有任何方法可以避免使用信号。它们是Unix为异步运行代码提供的唯一机制。

一定要注意在信号处理程序中可以做什么的许多限制;特别是,实际上整个标准C库都是禁止使用的。因此,你的"异步"回调可能不能做太多的事情,除了设置一个标志,告诉你的主事件循环在以后的某个时间做真正的工作。因此,无论如何,您可能不会从同步poll类型的模型中获得太多好处。

最新更新