用setitimer实现多个定时器
从这篇文章中可以看出,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实现多个定时器的更多相关文章
- linux系统编程之信号(八):三种时间结构及定时器setitimer()详解
一,三种时间结构 time_t://seconds struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microsecond ...
- Linux下的定时器
以下摘自linux下的man文件:(man getitimer) #include <sys/time.h> int getitimer(int which, struct iti ...
- linux c语言定时器
原文来自于:http://hi.baidu.com/opetrhsxszbckzd/item/126966cae5f9524aa9ba94f5 我只是把其重新排版标注一下. linux c语言定时器 ...
- Linux C定时器使用指南
使用定时器的目的是为了周期性的执行某一任务,或者是到了某个指定时间去执行某一任务.要达到这一目的,一般有两个常见的方法.一个是用linux内部的三个定时器,另一个是用sleep, usleep函数让进 ...
- Linux用户态定时器用法以及犯错总结【转】
转自:http://blog.csdn.net/csdn_logo/article/details/48525703 版权声明:本文为博主原创文章,欢迎转载,转载请注明出处,多谢合作. 采样的时候要用 ...
- Linux定时器的使用(三种方法)
使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务.要达到这一目的,一般有两个常见的比较有效的方法.一个是用linux内部的三个定时器,另一个是用sleep, us ...
- C语言编程技巧-signal(信号)[转]
自 http://www.uml.org.cn/c++/200812083.asp 信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用 ...
- Linux 多线程应用中如何编写安全的信号处理函数
http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...
- Linux信号(signal) 机制分析
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
随机推荐
- VirtualBox虚拟机内的系统时间无法调整的解决方法
VirtualBox虚拟机内的系统时间无法调整的解决方法 因试用某软件要求将系统时间设置在特定的日期,利用windows自带的调整日期/时间功能进行设置,发现过几秒钟就又恢复到和主机相同的时间了, ...
- java利用poi包 为excel生成超链接
转载自:http://www.blogjava.net/leekiang/archive/2008/10/21/235794.html 1,一个需求, 要求报表生成的Excel表格支持超链接.例如 ...
- android之截屏(包括截取scrollview与listview的)
public class ScreenShot { // 获取指定Activity的截屏,保存到png文件 public static Bitmap takeScreenShot(Activity a ...
- Jquery源码分析之匿名函数的自执行
匿名函数的格式: 格式: (function(){ //代码 })(); //和这个基于jQuery的比较下: $(function(){ alert("this is a test&quo ...
- C语言的32个保留字
auto :声明自动变量 double :声明双精度变量或函数 int: 声明整型变量或函数 struct:声明结构体变量或函数 break:跳出当前循环 else :条件语句否定分支(与 if 连用 ...
- 使用自由软件Icarus Verilog Simulator进行仿真
Icarus Verilog Simulator(http://iverilog.icarus.com/home)使用iverilog作为源代码编译器,编译生成vvp程序文本,使用vvp作为运行时引擎 ...
- OTL翻译(1) -- 说明
说明 该文档说明的是4.0版本的ORACLE/ODBC和DB2-CLI模板库(OTL).OTL4.0(后面简称OTL)模板库是基于C++的模板的. OTL4.0是组合了C++的模板框架和OTL适配器. ...
- Vue Cli安装以及使用
因为公司项目要用vue框架,所以会用vue-cli来新建项目.用过vue的都知道,要全局安装vue以及脚手架vue-cli,然后执行vue init webpack projectname来新建v ...
- 遇到Elements in iteration expect to have 'v-bind:key' directives.' 这个错误
解决方式一:更改VS Code编辑器的vetur配置 错误提示: [vue-language-server] Elements in iteration expect to have 'v-bind: ...
- IE浏览器报Promise未定义的错误、解决vuex requires a Promise polyfill in this browser问题
一个vue-cli构建的vue项目,一个使用angular的项目,两个项目在其他浏览器一切正常,但是ie中会报Promise未定义的错误 解决办法: 一.vue的项目: 1.npm install b ...