APUE习题10.5之implementing software timer
来源:互联网 发布:xbox one网络 编辑:程序博客网 时间:2024/05/18 07:14
题目:仅使用一个定时器,构造一组函数,使得进程在该单一定时器基础上可以设置任意数量的定时器。
具体思路请见http://www.cnblogs.com/CoreyGao/archive/2013/05/01/3053417.html,这篇译文已详细介绍,本文主要给出相应实现。
first mytimer.h
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <time.h>#include <unistd.h>#include <limits.h>#define TRUE 1#define FALSE 0#define MAX_TIMERS 100 // 最大定时器数#define VERY_LONG_TIME LONG_MAX // 最长定时数typedef time_t TIME; // 隐藏TIME的实现typedef void timer_handler(void *arg); volatile TIME time_now,time_set; // now为当前时间,set为当前定时器设置时间struct sigaction newact,oldact; // 设置sigalrm的处理程序sigset_t newmask,oldmask; // 设置屏蔽字struct timer{int inuse; // true if in useTIME time; // relative time to waittimer_handler *ahandler; // called when the timer has expiredvoid *arg; // arguemtn of handler}timers[MAX_TIMERS];struct timer *timer_next;void timer_init(void); // 初始化计时器struct timer* timer_declare(TIME,timer_handler*,void*); // 生成一个计时器void timer_undeclare(struct timer*); // 取消一个计时器void timer_update(); // 更新计时器数组,并获得下一个将要计时的计时器void timer_out_handler(int signo); // 信号处理函数void func(void *arg); // 自定义输出函数
second mytimer.c
#include "mytimer.h"static void disable_interrupt(void) // 关闭中断{sigemptyset(&newmask);sigaddset(&newmask,SIGINT);if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)fprintf(stderr,"sigprocmask error\n");}static void enable_interrupt(void) // 开启中断{if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)fprintf(stderr,"sigprocmask error\n");}void timer_init(void){int i;disable_interrupt();for(i = 0;i<MAX_TIMERS;i++)timers[i].inuse = FALSE; // 将计时器数组中每个计时器inuse状态设置为未用sigfillset(&newact.sa_mask); // 在处理信号时,阻塞所有信号的递送newact.sa_flags = 0;newact.sa_handler = timer_out_handler;if(sigaction(SIGALRM,&newact,&oldact) < 0){fprintf(stderr,"sigaction error\n");enable_interrupt();return;}enable_interrupt();}struct timer* timer_declare(TIME time_s,timer_handler *handler,void *arg){int i;disable_interrupt();for(i = 0;i<MAX_TIMERS;i++) // 找到第一个未用的计时器if(!timers[i].inuse)break;if(i == MAX_TIMERS) // 所有计时器都已用完{enable_interrupt();return NULL;}timers[i].time = time_s; // 计时器时间timers[i].ahandler = handler; // 计时器处理函数timers[i].arg = arg; // 处理函数参数if(!timer_next) // 当前计时器为唯一计时器{time_set = time(NULL); // 保存当前设置时间alarm((timer_next = &timers[i])->time); // 开始计时}else if(time_s < (timer_next->time - (time(NULL) - time_set))) // 比较当前计时器和当前正在计时的计时器的时间长度{timer_update(); // 更新每个计时器的计时timer_next = &timers[i]; // 设置新的当前正在计时的计时器time_set = time(NULL); // 记录设置时间alarm(timer_next->time); // 开始计时}timers[i].inuse = TRUE; // 最后再改变inuse防止update干扰enable_interrupt();return &timers[i];}void timer_undeclare(struct timer* t){disable_interrupt();if(!t->inuse){enable_interrupt();return;}t->inuse = FALSE;if(t == timer_next) // 如果是当前正在计时的计时器timer_update();enable_interrupt();}void timer_update() // 更新所有计时器时间,并将时间最短的设置为当前正在计时的计时器。{disable_interrupt();int i;static struct timer timer_last = {FALSE,VERY_LONG_TIME,NULL,NULL};timer_next = &timer_last;time_now = time(NULL); // 读取当前时间for(i = 0;i<MAX_TIMERS;i++){if(timers[i].inuse){timers[i].time -= time_now - time_set; // 所有计时更新if(timers[i].time < timer_next->time)timer_next = &timers[i]; // 更新当前正在计时的计时器}}if(timer_next->inuse) // 如果存在还未发生的定时器{alarm(timer_next->time);time_set = time(NULL);}elsetimer_next = NULL;enable_interrupt();}void timer_out_handler(int signo){timer_next->ahandler(timer_next->arg);timer_next->inuse = FALSE;timer_update(); // 寻找下一个执行的定时器}void func(void* arg){char *p = (char*)arg;printf("%s\n",p);}Contact GitHub API Training Shop Blog About © 2017 GitHub, Inc. Terms Privacy Security Status Help
third main.c
#include "mytimer.c"int main(){setbuf(stdout,NULL);timer_init();TIME time = 1;timer_declare(time,func,(void*)"hello world");time = 3;struct timer* t =timer_declare(time,func,(void*)"this is a test");time = 5;struct timer* m = timer_declare(time,func,(void*)"func(5)");timer_undeclare(t);while(1)pause();exit(0);}
运行结果
具体项目代码可见:https://github.com/xiaoHzp/apue/tree/master/ch10/simple10_5
阅读全文
0 0
- APUE习题10.5之implementing software timer
- APUE 习题10.5 - Implementing Software Timer
- apue习题10.5
- Implementing Software Timers
- Implementing Software Timers - Don Libes
- APUE课后习题4.6
- apue习题10.6
- apue 1 课后习题
- APUE习题10-6
- APUE习题16.4
- apue 习题6.3
- APUE习题3.2/3.6
- apue 习题4.6参考答案
- apue习题12.2实现
- Implementing the IEEE software engineering standards
- APUE 第二版 习题3.6
- [APUE] 第三章部分习题
- [APUE] 第四章习题解答
- 离散题目14
- yii的一些数据库查询方式(一)
- WebService 工作原理及实例教程
- JavaScript对象
- luban压缩多图路径重复问题解决
- APUE习题10.5之implementing software timer
- 实验吧——WriteUp&&涨姿势(4)
- 写接口Controller层
- 如何解决maven update之后JDK变回1.5
- cogs 577 蝗灾
- ADO.net 添加事务
- wifidog源码修改首页本地重定向
- Yii2框架数据库增删改查小结
- web端一个增删改查例子