0

问题一定很简单,但是..我不知道它是什么。它应该继续打印“alarm”一段时间,但它只打印一次,然后程序就死了:

#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

4 回答 4

1

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

  1. 它重置信号处理程序,

  2. 它重置警报

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

什么代码路径实际上达到了您的要求printf

于 2010-12-12T02:47:50.270 回答
1

sleep() 被信号中断,errno 设置为 EINTR。即在你的第一个闹钟之后,sleep() 返回并且你的程序在到达 main 结束时退出。

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

可能还有其他陷阱,请参见此处

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

于 2010-12-12T03:32:30.977 回答
0

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

于 2010-12-12T02:51:58.710 回答
0

我不知道你的程序,但这对我有用(代码取自这里):

#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);为 awhile (keep_going);main获得相同的结果。

问题是alarm它不在您程序的进程 ID 内执行,因此无论警报信号是否已触发,您的程序都可以结束。但是,sleep将程序的进程暂停n 秒,然后继续。如果没有某种方式来“暂停”进程,或者在等待警报时让进程保持活动状态,它就会在执行完所有必须执行的操作后死掉。即使使用没有 a sleep()、 awhile (...)a的线程,pthread_join()该进程也不会等待您的警报信号而只是结束(死亡)。因此,在等待信号被触发时,您需要以某种方式保持您的进程处于活动状态,否则它将无法工作。

于 2010-12-12T03:08:20.700 回答