用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内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
随机推荐
- java表格 JTable实例 (带滚动条,内嵌选择框)
import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.JScrollPa ...
- 快速入门:十分钟学会PythonTutorial - Learn Python in 10 minutes
This tutorial is available as a short ebook. The e-book features extra content from follow-up posts ...
- 如何利用启明星Portal门户系统的Page模块构建工作流表单
启明星门户网站的Pages模块支持构建自定义表单系统.这使得对于使用表单收集用户数据的需求来说非常有用. 本文介绍如何构建一个简单的“出差系统”. 1.在页面里增加Pages模块,建立人事部部门,然后 ...
- error: 'release' is unavailable: not available in automatic reference counting,该怎么解决
编译出现错误: 'release' is unavailable: not available in automatic reference counting mode.. 解决办法: You nee ...
- Cesium随笔(5)CZML介绍(介个文章是转的嘿嘿)【转】
通过czml可以在cesium上实现非常棒的动态效果 (1)Cesium Language (CZML) 入门--CZML Structure(CZML的结构) 原文地址:https://github ...
- C#调用C++ memcpy实现各种参数类型的内存拷贝 VS marshal.copy的实现 效率对比
using System; using System.Runtime.InteropServices; using System.IO; namespace tx { struct ST { publ ...
- 遇到问题描述:Android Please ensure that adb is correctly located at问题解决
遇到问题描述: 运行android程序控制台输出 [2013-11-04 16:18:26 - ] The connection to adb is down, and a severe error ...
- ORA-01843: 无效的月份,执行sql语句更改为美国语言后仍然失败的解决办法
ORA-01843: 无效的月份失败的 sql 为:XXXXXXXXXXXXXXXX 执行sql语句更改为美国语言后仍然失败, ALTER SESSION SET NLS_DATE_LANGUAGE= ...
- linux下线程调试 ulimit core
在linux 下写线程程序的同学预计都遇到过找bug找到崩溃的情况.多线程情况下bug的追踪实在是不easy. 如今我来介绍一个好用的方法 ulimit core. 先简介一下ulimit是个什么(你 ...
- JavaScript 之 日常积累
1. <a>标签"加入收藏",兼容IE,FireFox等 function bookmarksite() { if (window.sidebar) { // Mozi ...