这篇文章中可以看出,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;
}

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

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

用setitimer实现多个定时器的更多相关文章

  1. linux系统编程之信号(八):三种时间结构及定时器setitimer()详解

    一,三种时间结构 time_t://seconds   struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microsecond ...

  2. Linux下的定时器

    以下摘自linux下的man文件:(man  getitimer) #include  <sys/time.h> int  getitimer(int which,  struct iti ...

  3. linux c语言定时器

    原文来自于:http://hi.baidu.com/opetrhsxszbckzd/item/126966cae5f9524aa9ba94f5 我只是把其重新排版标注一下. linux c语言定时器 ...

  4. Linux C定时器使用指南

    使用定时器的目的是为了周期性的执行某一任务,或者是到了某个指定时间去执行某一任务.要达到这一目的,一般有两个常见的方法.一个是用linux内部的三个定时器,另一个是用sleep, usleep函数让进 ...

  5. Linux用户态定时器用法以及犯错总结【转】

    转自:http://blog.csdn.net/csdn_logo/article/details/48525703 版权声明:本文为博主原创文章,欢迎转载,转载请注明出处,多谢合作. 采样的时候要用 ...

  6. Linux定时器的使用(三种方法)

    使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务.要达到这一目的,一般有两个常见的比较有效的方法.一个是用linux内部的三个定时器,另一个是用sleep, us ...

  7. C语言编程技巧-signal(信号)[转]

    自 http://www.uml.org.cn/c++/200812083.asp 信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用 ...

  8. Linux 多线程应用中如何编写安全的信号处理函数

    http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...

  9. Linux信号(signal) 机制分析

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

随机推荐

  1. css3 实现圆角边框的border-radius属性和实现阴影效果的box-shadow属性

    首先我要介绍的是border-radius属性,它的作用是实现圆角边框,其中border-radius:20px;表示,一个’体‘四个角都圆滑20px,其值如果为100px那么圆角度则为最高,如果是正 ...

  2. AndEngine中文文档下载地址

    AndEngine doc  downloadhere 下载地址:http://pan.baidu.com/s/1bnjcL0V 文档是由github仓库AndEngine的代码生成. 本doc中包括 ...

  3. 数据库实例: STOREBOOK > 用户 > 编辑 用户: MGMT_VIEW

    ylbtech-Oracle:数据库实例: STOREBOOK  >  用户  >  编辑 用户: MGMT_VIEW 编辑 用户: MGMT_VIEW 1. 一般信息返回顶部 1.1, ...

  4. 第九章 Redis过期策略

    注:本文主要参考自<Redis设计与实现> 1.设置过期时间 expire key time(以秒为单位)--这是最常用的方式 setex(String key, int seconds, ...

  5. jqGrid常用属性和方法介绍

    jqGrid API中文手册:http://blog.mn886.net/jqGrid/ 一.jqGrid属性: width:Grid的宽度,如果未设置,则宽度应为所有列宽的之和:如果设置了宽度,则每 ...

  6. bind原理图释

    (原文:http://blog.think-async.com/2010/04/bind-illustrated.html) 本文解释了bind 是如何工作的.为了清晰,我对图中的语法作了一些简化(例 ...

  7. scala 学习笔记六 推导

    1.介绍 在Scala中,推导将生成器.过滤器.和定义组合在一起. 2.例子 有一种将result用作val(而不是var)的方式,:“就地”构建result,而不是逐项构建,利用yield关键字,当 ...

  8. scala 学习笔记一 列表List

    1.介绍 Scala 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:列表是不可变的,值一旦被定义了就不能改变,其次列表 具有递归的结构(也就是链接表结构)而数组不是.. 列表的元素类型 ...

  9. 【K8S】K8S-网络模型、POD/RC/SVC YAML 语法官方文档

    K8S-网络模型.POD/RC/SVC YAML 语法官方文档 Kubernetes - Production-Grade Container Orchestration kubernetes/kub ...

  10. hbase-0.94安装方法具体解释

    先决条件:     1)java环境,须要安装java1.6以上版本号     2)hadoop环境.因为HBase架构是基于其它文件存储系统的,因此在分布式模式下安装Hadoop是必须的,可是,假设 ...