Multiple alarms in C?

吃可爱长大的小学妹 提交于 2020-11-29 23:53:03

问题


This is probably a very basic question, but I'm using the code below to run a simple alarm. It works as I want it to, but I'm wondering if it's at all possible to run multiple alarms simultaneously that each trigger a different function when complete. Is there a way to do that?

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

回答1:


Not with alarm(2), however, you can use POSIX timers to achieve your goal.

Either you can set each timer to run a different signal when it expires or you can use a single signal and pass a pointer to the timer with it via siginfo_t, based on which you can then decide what to do in the handler.

Example:

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



回答2:


No. According to 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.

One alternative is to create a priority queue in which you put your tasks and then always schedule your alarm for the time difference between the current time and the task at the top of the queue.

But be sure to look at this SO question: you're limited in the kinds of things you can do inside your signal handler.



来源:https://stackoverflow.com/questions/44122139/multiple-alarms-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!