应用层使用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. hduoj----(1033)Edge

    Edge                         Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ( ...

  2. web实现QQ第三方登录 开放平台-web实现QQ第三方登录

    应用场景     web应用通过QQ登录授权实现第三方登录.   操作步骤     1  注册成为QQ互联平台开发者,http://connect.qq.com/     2  准备一个可访问的域名, ...

  3. Linux命令-终止进程命令:killall

    强制杀死所有进程,注意它后面跟着是进程名而不是进程号 killall - httpd 杀死apache所有进程pstree -p | grep httpd 查看apache进程就没有了service ...

  4. 使用Wireshark mac下抓取分析iphone数据包 --IOS端

    mac系统版本:mac 10.10 Yosemite xcode版本:6.3.1 在追踪bug或者分析借鉴其他公司的app通讯思路时,抓包这件事是非常有必要的.下面说说Wireshark怎么截获iph ...

  5. C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求

    C# 动态创建SQL数据库(二) 使用Entity Framework  创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...

  6. python matplotlib.pyplot画矩形图 以及plt.gca()

    plt的Rectangle参数: 第一个参数是坐标(x,y),即矩形的画图的起点坐标,这个起点坐标不是一味地从左下角开始画,而是对应整个图中坐标原点,即(0,0). 第二个参数是矩形宽度 第三个坐标是 ...

  7. Chrome 错误代码:ERR_UNSAFE_PORT

    最近在用Nginx发布多个站点测试,使用了87.88端口, 88端口访问正常,87端口就怎么也访问不了, 点击更多,提示错误代码:ERR_UNSAFE_PORT 不安全的端口?尼玛就只靠端口就能解决不 ...

  8. 【转】其他人的BUG

    在软件行业,经常看到有的公司管理让一个人修补另一个人代码里的BUG.有时候有人写了一段代码,扔出来不管了,然后公司管理让其他工程师来修复它.我想告诉你们,这种方法会很失败. 首先,让一个人修复另一个人 ...

  9. 文件描述符file descriptor与inode的相关知识

    每个进程在Linux内核中都有一个task_struct结构体来维护进程相关的 信息,称为进程描述符(Process Descriptor),而在操作系统理论中称为进程控制块 (PCB,Process ...

  10. 深入mysql “ON DUPLICATE KEY UPDATE” 语法的分析

    本篇文章是对mysql “ON DUPLICATE KEY UPDATE”语法进行了详细的分析介绍,需要的朋友参考下. mysql “ON DUPLICATE KEY UPDATE” 语法 如果在IN ...