C unix中的信号/警报问题

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

问题一定很简单,但我搞不懂是什么问题。它应该继续打印“alaarm”一段时间,但只打印一次,然后程序就会死掉:

#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;
    }