从这篇文章中可以看出,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
");
}
void func2()
{
printf("timer2
");
}
void func3()
{
printf("timer3
");
}
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;
}
当然,用堆实现定时器的维护效果会更好。
未经允许请不要随意转载代码,谢谢。