C unix中的信号/警报问题
问题一定很简单,但我搞不懂是什么问题。它应该继续打印“alaarm”一段时间,但只打印一次,然后程序就会死掉:C unix中的信号/警报问题,c,unix,signals,alarm,C,Unix,Signals,Alarm,问题一定很简单,但我搞不懂是什么问题。它应该继续打印“alaarm”一段时间,但只打印一次,然后程序就会死掉: #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <signal.h> void onAlarm(); void setupAlarm() { signal(SIGALRM, onAlarm); alarm(1); } void onAla
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
void onAlarm();
void setupAlarm() {
signal(SIGALRM, onAlarm);
alarm(1);
}
void onAlarm() {
setupAlarm();
printf("alarmmmmmmmmmmmmmmmmm\n");
}
void main()
{
setupAlarm();
sleep(1000);
}
但我仍在努力理解为什么需要这样编写代码。哎呀,我以前的回答完全错了。查看调用
onAlarm()
时发生的情况:
什么代码路径实际到达您的printf调用?首先,您告诉您的环境在一秒钟后生成一个SIGALRM,然后在一秒钟后退出。尝试将等待时间增加到两秒。我不知道您的程序,但这对我来说很有效(代码取自:
#包括
#包括
#包括
#包括
无效捕捉报警(int sig);
无效设置报警();
/*此标志控制主循环的终止*/
挥发性sig_原子不持续=4;
/*信号处理程序只是清除标志并重新启用自身*/
无效捕捉报警(int sig){
继续;
printf(“报警!!\n”);
如果(继续){
设置报警();
}
}
无效设置报警(){
警报(1);
睡眠(1);
}
int main(int argc,字符**argv){
信号(信号报警、捕捉报警);
设置报警();
返回退出成功;
}
这将打印四个警报代码>然后退出
您可以替换睡眠(1)代码>与同时进行(继续)在main
中选择code>,以获得相同的结果
问题在于报警
不会在程序的进程id内执行,因此无论报警信号是否已触发,程序都可以结束。但是,sleep
将程序的进程保持n秒,然后继续。如果没有某种方法来“暂停”进程,或者在等待警报时保持进程的活动状态,那么它将在执行了所有必须执行的操作后死亡。即使使用线程,如果没有sleep()
,没有while(…)
,等等和pthread\u join()
,进程也不会等待您的报警信号,而只是结束(死亡)。因此,在等待信号触发时,您需要以某种方式保持进程处于活动状态,否则它将无法工作。sleep()被信号中断,并且errno设置为EINTR。i、 e.在第一次报警后,sleep()返回,当程序到达main的末尾时退出
注意,您不应该从信号处理程序调用printf,printf不是信号异步安全的
也许还有其他的陷阱,明白吗
我无法复制您的原始代码的行为—不打印任何内容,但如果您想知道发生了什么,只需使用或类似的工具运行您的程序。我不太理解“旧的默认信号返回”的含义。如果可能的话,你能说得更清楚一点吗?我用的是Ubuntu 10.10,没关系,反正那是错的。但在BSD UNIX和SysV UNIX中,信号(2)和相关系统调用的语义不同;有些人(呜呜)已经长大了,记得这件事发生过。我还是不明白你想去哪里。重置sinal处理程序似乎不是问题。问题是它忽略了最初的睡眠。请参阅我的原始帖子上的编辑。@Owned elysium,alarm
!=<代码>睡眠
,见我的回答我猜你指的是睡眠?unix中的睡眠是以秒为单位的,所以1000是1000秒。“我没弄错吧?”吞食者:啊,我错了。我已经有一段时间没有用C了。只是一个便条,以确保你知道这一点。如果在sleep()期间被信号唤醒,则对sleep()的调用将返回该睡眠中剩余的秒数。它不会继续等待剩余的时间。阅读“警报”和“睡眠”的手册页可以准确地告诉你发生了什么(它们很短——你可以在撰写这篇文章的时间内完整地阅读它们)。如果OP希望它永远运行,则替换sleep(1000)代码>与同时(1)暂停()代码>
void onAlarm() {
printf("alarmmmmmmmmmmmmmmmmm\n");
alarm(1);
sleep(1);
}
void main()
{
signal(SIGALRM, onAlarm);
alarm(1);
sleep(2);
}
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void catch_alarm (int sig);
void setupAlarm();
/* This flag controls termination of the main loop. */
volatile sig_atomic_t keep_going = 4;
/* The signal handler just clears the flag and re-enables itself. */
void catch_alarm (int sig) {
keep_going--;
printf("Alarm!!\n");
if (keep_going) {
setupAlarm();
}
}
void setupAlarm() {
alarm(1);
sleep(1);
}
int main (int argc, char **argv) {
signal(SIGALRM, catch_alarm);
setupAlarm();
return EXIT_SUCCESS;
}