unix中的信号/报警问题

时间:2010-12-12 02:40:30

标签: 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 onAlarm() {
 setupAlarm();
 printf("alarmmmmmmmmmmmmmmmmm\n");
}

void main()
{
 setupAlarm();
 sleep(1000);
}

这里可能有什么问题?取出sleep(1000)会使程序瞬间死亡(也就是说,即使没有显示那个“alaaarm”)。

答案

好的,以下代码可以运行:

void onAlarm() {
    printf("alarmmmmmmmmmmmmmmmmm\n");
    alarm(1);
    sleep(1);
}

void main()
{
    signal(SIGALRM, onAlarm);
    alarm(1);
    sleep(2);
}

但是我仍然围绕着这个并尝试理解为什么我需要像这样编码。

4 个答案:

答案 0 :(得分:1)

哎呀,我之前的回答是完全错误的。看看调用onAlarm()时会发生什么:

  1. 重置信号处理程序,

  2. 重置警报

  3. 它在取消之前的闹钟后再次开始等待。

  4. 实际到达printf

    的电话的代码路径是什么?

答案 1 :(得分:1)

sleep()被信号中断,errno被设置为EINTR。即,在第一次报警后,sleep()返回,程序在到达main结束时退出。

请注意,您不应该从信号处理程序调用printf,printf不是信号异步安全。

可能还有其他陷阱,请参阅here

我无法重现原始代码的行为而不能打印任何内容,但如果您想知道发生了什么,只需在strace或类似工具下运行您的程序。

答案 2 :(得分:0)

嗯,对于初学者,你告诉你的环境在一秒钟之后生成一个SIGALRM,然后在一秒之后退出。尝试将等待时间增加到两秒钟。

答案 3 :(得分:0)

我不了解你的程序,但这对我有用(代码来自here):

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

这将打印四个Alarm!然后退出。

您可以使用sleep(1);中的while (keep_going);替换main以获得相同的结果。

问题是alarm未在程序的进程ID中执行,因此程序可以结束是否已触发警报信号。但是,sleep会将您的程序进程置于 hold n秒,然后继续。如果没有某种方法来“暂停”该过程,或者在等待警报的同时保持进程活着,那么它将会执行必须执行的所有操作。即使使用线程,没有sleep()while (...) a pthread_join(),该过程也不会等待您的警报信号并且结束(死)。因此,您需要在等待信号被触发时以某种方式保持您的进程存活,否则它将无法工作。