众所周知,在信号处理程序中做事真的很糟糕,因为它们在类似中断的上下文中运行。调用信号处理程序时,很可能会持有各种锁(包括 malloc() 堆锁!)。
所以我想在不使用信号机制的情况下实现一个线程安全的计时器。
我能怎么做?
抱歉,实际上,我并不期待有关线程安全的答案,而是有关在 Unix 或 Linux 上实现线程安全的计时器的答案。
众所周知,在信号处理程序中做事真的很糟糕,因为它们在类似中断的上下文中运行。调用信号处理程序时,很可能会持有各种锁(包括 malloc() 堆锁!)。
所以我想在不使用信号机制的情况下实现一个线程安全的计时器。
我能怎么做?
抱歉,实际上,我并不期待有关线程安全的答案,而是有关在 Unix 或 Linux 上实现线程安全的计时器的答案。
在你的线程中使用 usleep(3) 或 sleep(3)。这将阻塞线程,直到超时到期。
如果您需要等待 I/O 并且在任何 I/O 准备好之前让计时器到期,请使用 select(2)、poll(2) 或 epoll(7) 并设置超时。
如果您仍然需要使用信号处理程序,请使用 pipe(2) 创建管道,在线程的读取端执行阻塞读取,或使用 select/poll/epoll 等待它准备好,然后写入一个字节使用 write(2) 到信号处理程序中管道的写入端。你写什么到管道中并不重要——这个想法只是让你的线程唤醒。如果要在一个管道上多路复用信号,请将信号编号或其他 ID 写入管道。
您可能应该使用pthreads
POSIX 线程库之类的东西。它不仅提供线程本身,还提供基本的同步原语,如互斥体(锁)、条件、信号量。这是我发现似乎不错的教程:
http ://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
对于它的价值,如果您完全不熟悉多线程编程,那么在 Java 或 Python 中学习它可能比在 C 中更容易一些,如果您知道其中任何一个。
我认为解决您描述的问题的通常方法是让信号处理程序只做最少量的工作。例如设置一些 timer_expired 标志。然后你有一些线程定期检查标志是否已设置,并执行实际工作。
如果您不想使用信号,我想您必须让线程休眠或忙等待指定的时间。
使用 Posix 间隔计时器,并通过信号通知它。在信号处理函数内部,几乎没有 C 的函数,如 printf() 可以使用,因为它们不是可重入的。
使用单个全局标志,声明为静态 volatile供信号处理程序操作。处理程序应该有这一行代码,没有别的;这个标志应该影响程序中 1 & Only 线程中其他地方的流控制。
static volatile bool g_zig_instead_of_zag_flg = false;
...
void signal_handler_fnc()
g_zig_instead_of_zag_flg = true;
return
int main() {
if(false == g_zig_instead_of_zag) {
do_zag();
} else {
do_zig();
g_zig_instead_of_zag = false;
return 0;
}
Michael Kerrisk 的The Linux Programming Interface 有这两种方法的示例,还有一些示例,但是这些示例带有很多他自己的私有函数,你必须开始工作,并且这些示例小心地避免了他们应该探索的许多陷阱,所以不伟大的。
使用通过线程通知的 Poxix 间隔计时器会使一切变得更糟,而 AFAICT,该通知方法几乎没用。我之所以这么说是因为我允许在某些情况下在 main() 线程中什么都不做,而处理程序线程中的所有内容都是有用的,但我肯定想不出任何这样的情况。