alarm()
调用是用于单次信号的。
要重复一个闹钟,您必须在每次发生信号时再次调用
alarm()
。
另一个问题是,您很可能会收到
EINTR
错误。许多系统函数在接收到信号时会被中断。这使得编程变得更加复杂,因为许多操作系统函数会受到影响。
无论如何,等待下一个
SIGALRM
的正确方法是使用
pause()
函数。其他人没有提到的一件事是(他们使用紧密循环,很丑陋!)
话虽如此,如果您只想要一个简单的
sleep()
调用,那么您尝试做的事情将变得更加容易:
// print a message every second (simplified version)
for(;;)
{
printf("My Message\n");
sleep(1);
}
这样的循环可以出现在一个单独的线程中。然后,您不需要Unix信号来实现此功能。
注意:sleep()
函数实际上使用与alarm()
相同的定时器,明确指出您不应在同一代码中混合使用两个函数。
sleep(3)
可能使用SIGALRM
实现;调用alarm()
和sleep(3)
混合使用是不好的做法。
(来自Linux man alarm
)
void alarm_handler(int)
{
alarm(1);
}
int main(int argc, char *argv[])
{
signal(SIGALRM, alarm_handler);
alarm(1);
for(;;)
{
printf("My Message\n");
pause();
}
return 0;
}
您可以创建变量。例如,如果您希望第一条消息在1秒后而不是立即发生,请将
pause()
移至
printf()
之前。
“其他工作”注释假设您的其他工作不超过1秒。
如果需要并行工作,则可以在特定线程上获得警报信号,但是如果需要任何其他计时器(即,您不能轻松地与其他函数共享
alarm()
计时器),则可能会变得复杂。
附言:正如其他人所提到的,将您的
printf()
放在信号处理程序中根本不是一个好主意。
还有另一个版本,在其中
alarm()
在
main()
内被重置,第一条消息出现在1秒后,并且循环运行60秒(1分钟):
void alarm_handler(int)
{
}
int main(int argc, char *argv[])
{
signal(SIGALRM, alarm_handler);
for(int seconds(0); seconds < 60; ++seconds)
{
alarm(1);
pause();
printf("My Message\n");
}
return 0;
}
请注意,使用此方法打印消息的时间将会被扭曲。在重新启动闹钟之前,打印消息的时间被添加到时钟中...因此每次调用之间始终会有略微超过1秒的间隔。另一个循环在这方面更好,但仍然存在偏差。对于一个完美(更好)的定时器,
poll()
函数要好得多,因为您可以指定下一次唤醒的时间。
poll()
只能与计时器一起使用。我的
Snap库使用了这个功能(在文件底部查找
run()
函数)。在2019年,我将那个.cpp文件移动到
eventdispatcher库中。
run()
函数在
communicator.cpp
文件中。