C中的多个警报?

Multiple alarms in C?

这可能是一个非常基本的问题,但我正在使用下面的代码 运行 一个简单的警报。它按照我的意愿工作,但我想知道是否有可能同时 运行 多个警报,每个警报在完成时触发不同的功能。有办法吗?

#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <time.h>

void alarm_handler(int signum){
    printf("five seconds passed!!\n");
}
int main(){
    signal(SIGALRM, alarm_handler);
    alarm(5);

    pause();
    return 0;
}

没有。根据this source:

Alarm requests are not stacked; only one SIGALRM generation can be scheduled in this manner. If the SIGALRM signal has not yet been generated, the call shall result in rescheduling the time at which the SIGALRM signal is generated.

一种替代方法是创建一个 priority queue,在其中放置任务,然后始终根据当前时间与队列顶部任务之间的时差安排闹钟。

但请务必查看 this SO 问题:您在信号处理程序中可以做的事情种类有限。

不使用 alarm(2),但是,您可以使用 POSIX 计时器来实现您的目标。

您可以将每个定时器在到期时设置为 运行 不同的信号,或者您可以使用单个信号并通过 siginfo_t 将指针传递给定时器,基于此然后可以决定在处理程序中做什么。

示例:

#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

static timer_t tmid0, tmid1;

static void hndlr(int Sig, siginfo_t *Info, void *Ptr)
{
    if(Info->si_value.sival_ptr == &tmid0)
        write(2, "tmid0\n", 6);
    else{
        write(2, "tmid1\n", 6);
        _exit(0);
    }
}


int main()
{
    int r = EXIT_SUCCESS;

    sigaction(SIGALRM, &(struct sigaction){ .sa_sigaction = hndlr, .sa_flags=SA_SIGINFO }, 0);
    printf("%p %p\n", (void*)&tmid0, (void*)&tmid1);

    struct sigevent sev = { .sigev_notify = SIGEV_SIGNAL, .sigev_signo = SIGALRM };

    sev.sigev_value.sival_ptr = &tmid0; 
    if(0>timer_create(CLOCK_REALTIME,&sev,&tmid0))
        { r=EXIT_FAILURE; goto out; }

    sev.sigev_value.sival_ptr = &tmid1; 
    if(0>timer_create(CLOCK_REALTIME,&sev,&tmid1))
        { r=EXIT_FAILURE; goto out; }

    if(0>timer_settime(tmid0, 0, &(struct  itimerspec const){ .it_value={1,0} } , NULL) )
        { r=EXIT_FAILURE; goto out; }
     //tmid0 expires after 1 second

    if(0>timer_settime(tmid1, 0, &(struct  itimerspec const){ .it_value={3,0} } , NULL) )
        { r=EXIT_FAILURE; goto out; }
     //tmid1 expires after 3 seconds


    for(;;)
        pause();

out:
    if(r)
        perror(0); 
    return r;
}