用setitimer实现多个定时器

时间:2022-04-27 02:14:11

这篇文章中可以看出,setitimer只能实现一个定时器,如果多次调用setitimer,旧值都会被覆盖掉。

如何用setitimer实现多个定时器呢?下面是我的一个实现,具体的方法是:

用链表从小到大维护这些定时器的信息,表头元素的定时器时间最短。当有新的定时器加入时,将它插入到合适的位置;当一个定时时间到达后,更新链表中所有定时器的剩余时间,再次调用setitimer。

 

废话不多说,直接上代码:

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

typedef struct my_timer_s my_timer_t;

struct my_timer_s {
    my_timer_t *prev, *next;
    int diff_sec;
    int diff_usec;
    void (*func)();
};

my_timer_t  *timer_list = NULL;

void callback_timeout()
{
    my_timer_t *p, *q;
    struct itimerval itimer;
    sigset_t set, oldset;

    p = timer_list;

    sigemptyset(&set);
    sigaddset(&set, SIGALRM);
    sigprocmask(SIG_SETMASK, &set, &oldset);

    for (q = timer_list->next; q; q = q->next) {
        q->diff_sec -= p->diff_sec;
        q->diff_usec -= p->diff_usec;
    }

    if (timer_list->next != NULL) {
        timer_list = timer_list->next;

        itimer.it_interval.tv_sec = 0;
        itimer.it_interval.tv_usec = 0;
        itimer.it_value.tv_sec = timer_list->diff_sec;
        itimer.it_value.tv_usec = timer_list->diff_usec;

        setitimer(ITIMER_REAL, &itimer, NULL);
    }

    sigprocmask(SIG_SETMASK,&oldset,NULL);

    p->func();

    free(p);
}

int register_timer(int sec, int usec, void (*action)())
{
    my_timer_t  *t, *p, *pre;
    struct itimerval itimer;
    struct sigaction sa;
    sigset_t set, oldset;

    t = (my_timer_t *) malloc(sizeof(my_timer_t));
    t->next = t->prev = NULL;
    t->diff_sec = sec;
    t->diff_usec = usec;
    t->func = action;

    sigemptyset(&set);
    sigaddset(&set, SIGALRM);
    sigprocmask(SIG_SETMASK,&set,&oldset);

    if (timer_list == NULL) {

        timer_list = t;

    } else {

        for (pre = NULL, p = timer_list; p; pre = p, p = p->next) {
            if (p->diff_sec > t->diff_sec ) {
                t->next = p;
                p->prev = t;

                if (p->prev) {
                    p->prev->next = t;
                    t->prev = p->prev;
                }

                break;
            }
        }

        if (p == NULL) {
            t->prev = pre;
            pre->next = t;
        }
    }

    t = timer_list;

    itimer.it_interval.tv_sec = 0;
    itimer.it_interval.tv_usec = 0;
    itimer.it_value.tv_sec = t->diff_sec;
    itimer.it_value.tv_usec = t->diff_usec;
    setitimer(ITIMER_REAL, &itimer, NULL);

    sigprocmask(SIG_SETMASK, &oldset, NULL);

    return 0;
}

void func1()
{
    printf("timer1\n");
}


void func2()
{
    printf("timer2\n");
}


void func3()
{
    printf("timer3\n");
}


void timer_handler (int signo)
{
    switch(signo) {
    case SIGALRM:
        callback_timeout();
        break;
    }
}

int main ()
{
    struct sigaction sa;
    struct itimerval itimer;

    /*
    memset (&sa, 0, sizeof (sa));
    sa.sa_handler = &timer_handler;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, NULL);
    */
    signal(SIGALRM, timer_handler);

    register_timer(1, 0, &func1);
    register_timer(4, 0, &func2);
    register_timer(5, 0, &func3);

    while (1);

    return 0;
}

  当然,用堆实现定时器的维护效果会更好。

 

未经允许请不要随意转载代码,谢谢。