应用层使用timer可以启动多个timer(每个timer管理一个目标时间),也可启用一个timer来管理多个目标时间。

多个timer时每个timer占用一部分空间,且存在多个timer同时到期的先后顺序问题(未多考虑,是否有问题待确定),可采用单个timer管理程序所有定时事件,即如何实现序列化的timer。

涉及到链表(记录多个目标时间的到期时间),信号处理函数(在SIG_ALAM函数中处理timer事件,并启动下一个timer时间点)。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <string.h> #include "list.h" #define TIMERID_FIRST 100 typedef void (*stimer_func)(void *arg); struct signal_timer{
struct list_head list_timer;
int id;
struct timeval itv;
struct timeval atv;
stimer_func stimer_handler;
void *arg;
}; int g_id;
struct list_head g_signal_list; void alarm_handler(int sig);
int timer_init(void);
void timer_destroy(void);
// Return: id >0, in case of success; -1 in case of error.
int timer_add(long sec, long usec, void (*stimer_func)(void *arg), void *arg);
void timer_del(int id, int is_free); static long long diff_time(struct timeval *t1, struct timeval *t2)
{
long long t1_usec = (t1->tv_sec * * + t1->tv_usec);
long long t2_usec = (t2->tv_sec * * + t2->tv_usec); return (t1_usec - t2_usec);
}
static int max_time(struct timeval *t1, struct timeval *t2)
{
if(t1->tv_sec < t2->tv_sec){
return -;
} else if(t1->tv_sec > t2->tv_sec){
return ;
} else {
if(t1->tv_usec < t2->tv_usec){
return -;
} else if(t1->tv_usec > t2->tv_usec){
return ;
} else {
return ;
}
}
} #define min_time(t1, t2) (((t1).tv_sec < (t2).tv_sec) || \
(((t1).tv_sec == (t2).tv_sec) && \
((t1).tv_usec < (t2).tv_usec))) #define MAX_USEC 999999
#define TV_MINUS(t1, t2, target) if((t1).tv_usec >= (t2).tv_usec){ \
(target).tv_sec = (t1).tv_sec - (t2).tv_sec;\
(target).tv_usec = (t1).tv_usec - (t2).tv_usec;\
} else { \
(target).tv_sec = (t1).tv_sec - (t2).tv_sec - ;\
(target).tv_usec = (t1).tv_usec + (MAX_USEC - (t2).tv_usec);\
}
void alarm_handler(int sig)
{
struct timespec ts;
struct timeval tv;
struct timeval tv_min, *ptv_min;
struct itimerval it;
struct signal_timer *pstimer = NULL, *next= NULL;
int ret = ; if(list_empty(&g_signal_list))
return ; // pstimer = list_first_entry(&g_signal_list, struct signal_timer, list_timer);
// ptv_min = &(pstimer->atv);
ptv_min = &tv_min; clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / ;
// printf("now time: %ld:%ld\n", tv.tv_sec, tv.tv_usec); tv_min = tv;
tv_min.tv_sec += ; //default 1000s once // two methods: sequence the timer list in case of more timers,
// not sequence in case of fewer timers.
list_for_each_entry_safe(pstimer, next, &g_signal_list, list_timer){
// printf("timerid:%d, aim time: %ld:%ld\n", pstimer->id, pstimer->atv.tv_sec, pstimer->atv.tv_usec);
if(max_time(&pstimer->atv, &tv) <= ){
if(pstimer->stimer_handler != NULL){
pstimer->stimer_handler(pstimer->arg);
}
// only operation once, when overflow more times.
do{
pstimer->atv.tv_sec += pstimer->itv.tv_sec;
pstimer->atv.tv_usec += pstimer->itv.tv_usec;
} while(max_time(&pstimer->atv, &tv) < );
// } else {
// break;
}
// get next itimer
if(min_time(pstimer->atv, *ptv_min)){
ptv_min = &(pstimer->atv);
}
} memset(&it, , sizeof(it));
// it.it_value.tv_sec = ptv_min->tv_sec - tv.tv_sec;
// it.it_value.tv_usec = ptv_min->tv_usec - tv.tv_usec;
TV_MINUS(*ptv_min, tv, it.it_value);
ret = setitimer(ITIMER_REAL, &it, NULL);
if(ret < ){
perror("setitimer");
}
printf("process SIGALRM, next time is %ld:%ld\n", it.it_value.tv_sec, it.it_value.tv_usec);
} int timer_add(long sec, long usec, void (*stimer_func)(void *arg), void *arg)
{
struct signal_timer *pstimer = (struct signal_timer*)malloc(sizeof(struct signal_timer));
struct timespec ts; memset(pstimer, , sizeof(*pstimer));
pstimer->id = g_id++;
pstimer->itv.tv_sec = sec;
pstimer->itv.tv_usec = usec;
pstimer->stimer_handler = stimer_func;
if(arg){
pstimer->arg = arg;
}else {
pstimer->arg = pstimer;
} list_add(&(pstimer->list_timer), &g_signal_list); clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
pstimer->atv.tv_sec += ts.tv_sec;
pstimer->atv.tv_usec += ts.tv_nsec / ; return pstimer->id;
}
void timer_del(int id, int is_free)
{
struct signal_timer *pstimer = NULL; list_for_each_entry(pstimer, &g_signal_list, list_timer){
if(pstimer->id == id){
list_del(&(pstimer->list_timer)); printf("----delete timerid is %d\n", pstimer->id);
if(is_free){
free(pstimer);
}
break;
}
}
} int timer_init(void)
{
INIT_LIST_HEAD(&g_signal_list);
struct sigaction act;
int ret = ; // memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_handler = alarm_handler;
act.sa_flags = ; ret = sigaction(SIGALRM, &act, NULL);
if(ret < ){
perror("sigaction");
return -;
} g_id = TIMERID_FIRST ; return ;
}
void timer_destroy(void)
{
struct signal_timer *pstimer = NULL; while(! list_empty((&g_signal_list)->next)){
list_del((&g_signal_list)->next);
pstimer = container_of((&g_signal_list)->next, struct signal_timer, list_timer);
free(pstimer);
}
} void timer_printf(void *arg)
{
if(arg){
struct signal_timer *pstimer = (struct signal_timer*)arg;
printf("timerid:%d, aim time: %ld:%ld\n", pstimer->id, pstimer->atv.tv_sec, pstimer->atv.tv_usec);
} else {
printf("timerid is %d\n", g_id);
}
}
int main(int argc, char **argv)
{
int tid1 = , tid2 = , tid3 = ;
int i = ; signal(SIGPIPE, SIG_IGN);
timer_init(); tid1 = timer_add(, , timer_printf, NULL);
tid2 = timer_add(, , timer_printf, NULL);
tid3 = timer_add(, , timer_printf, NULL); alarm();
while(){
sleep();
printf("sleep 1s\n");
i++;
if(i% == ) timer_del(tid1, true);
if(i% == ) timer_del(tid2, true);
if(i% == ) timer_del(tid3, true);
} timer_destroy(); return ;
}

运行:

timerid:, aim time: :
timerid:, aim time: :
timerid:, aim time: :
process SIGALRM, next time is :
sleep 1s
timerid:, aim time: :
process SIGALRM, next time is :
sleep 1s
timerid:, aim time: :
process SIGALRM, next time is :
sleep 1s
----delete timerid is
process SIGALRM, next time is :
sleep 1s
timerid:, aim time: :
process SIGALRM, next time is :
sleep 1s
timerid:, aim time: :
process SIGALRM, next time is :
sleep 1s
sleep 1s
----delete timerid is
sleep 1s
process SIGALRM, next time is :
sleep 1s
----delete timerid is
sleep 1s
sleep 1s
sleep 1s
sleep 1s

应用层timer_如何序列化timer的更多相关文章

  1. 基于Protobuf的分布式高性能RPC框架——Navi-Pbrpc

    基于Protobuf的分布式高性能RPC框架——Navi-Pbrpc 二月 8, 2016 1 简介 Navi-pbrpc框架是一个高性能的远程调用RPC框架,使用netty4技术提供非阻塞.异步.全 ...

  2. 定时器管理:nginx的红黑树和libevent的堆

    libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到ac ...

  3. 介绍开源的.net通信框架NetworkComms框架 源码分析(二十 )ConnectionCreate

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是 ...

  4. 【linux】驱动-15-定时器

    目录 前言 15. 定时器 15.1 内核函数汇总 15.2 内核滴答 15.3 相关结构体 15.4 setup_timer() 设置定时器 15.5 add_timer() 向内核添加定时器 15 ...

  5. 应用层timer_libc_posix timer

    应用层除了通过setitimer/getitimer设置获取timer外,还可通过timer_create()等一系列函数实现应用层timer功能. 应用流程 The timers created b ...

  6. Linux应用层的定时器Timer使用详解【转】

    转自:http://blog.csdn.net/wwwtovvv/article/details/8601528 版权声明:本文为博主原创文章,未经博主允许不得转载. linux下定时器的使用 -- ...

  7. [Timer]应用层实现sleep

    转自:https://www.cnblogs.com/longbiao831/p/4556246.html Select只能做延时,可以做回调吗? 本文讲述如何使用select实现超级时钟.使用sel ...

  8. ABP(现代ASP.NET样板开发框架)系列之16、ABP应用层——数据传输对象(DTOs)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之16.ABP应用层——数据传输对象(DTOs) ABP是“ASP.NET Boilerplate Project ...

  9. Android序列化之Serializable和Parcelable

    PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...

随机推荐

  1. js ie下有效 showModalDialog 、showModelessDialog

    <input type="button" value="打开选择输入框"/> <script type="text/javascri ...

  2. [转]linux内核网络分层结构

    Preface   Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程 ...

  3. 【LeetCode】164. Maximum Gap (2 solutions)

    Maximum Gap Given an unsorted array, find the maximum difference between the successive elements in ...

  4. 【LeetCode】130. Surrounded Regions (2 solutions)

    Surrounded Regions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A ...

  5. Linux命令-统计文件中的字节数、字数、行数:wc

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...

  6. Fix-Mapped Addresses

    一.前言 某天,wowo同学突然来了一句:如果要在start_kernel中点LED,ioremap在什么时间点才能调用呢?我想他应该是想通过点LED灯来调试start_kernel之后的初始化的代码 ...

  7. win7下安装ubuntu双系统的方法及心得体会(ps:要死好几回的节奏)

    1.win7下安装ubuntu系统后,可以很好进入ubuntu系统 但是进不去win7,开机有win7选项,但是选择后不管用 方法思路:各种修复win7的mbr 我的问题是:在winpe中发现,根本看 ...

  8. dubbo-admin 管理台的部署

    首先上传dubbo-admin的war包 参考链接: http://www.open-open.com/lib/view/open1454043410245.html

  9. uva--242(邮资问题 dp)

    输入输出: id=26127" style="color:blue; text-decoration:none">Sample Input 5 2 4 1 4 12 ...

  10. express 设置node_env的环境变量

    设置process.env.NODE_ENV的环境变量可以用以下2种方式: //在你的app.js文件中设置 process.env.NODE_ENV = 'development'; //在pack ...