APUE 习题10.5 - Implementing Software Timer
来源:互联网 发布:安知鸿鹄之志上一句 编辑:程序博客网 时间:2024/06/04 17:49
这是我自己实现的版本,参考 Don Libes 的 Implementing Software Timer
我是用alarm实现的,好像不太精确,还有一个版本可以设定定时器的次数,可是随着次数增多精确度就成了不可忽略的问题了。
不排除有很多BUG, 而且有些细节没考虑。
/************** timers.h *************//* * Title: Answer to excersice 10.5 of APUE - Software timer * By: Leon * * This implementation is similar to Don Libes's, and I modify * it according to my thought. This timer is not very precise. */#ifndef _APUE_TIMER_#define _APUE_TIMER_#include <stdio.h>#include <limits.h>#include <signal.h>#include <sys/times.h>#include <time.h>#include <assert.h>#include <unistd.h>#define TRUE 1#define FALSE 0#define MAX_TIMERS 128 /* number of timers */#define VERY_LONG_TIME INT_MAX /* longest time possible *//* * no return value, the function takes * only one parameter for general purpose. */typedef void timer_handler(void *arg); struct __apue_timer{ int inuse; /* TRUE if in use */ int time_wait; /* relative time to wait */ timer_handler *handler; /* called when the timer has expired */ void *arg; /* argument of handler */};typedef struct __apue_timer ATIMER;/* * initialize the timers array. * This function must be called first. * returns 0 on success and -1 on error. */int timer_init(void);/* * stop and cancel all timers. * after this function was called, don't use functions * declared here before timer_init() was called. */void timer_cancel(void);/* * Function : decalre a timer * Parameter : time_set sets the time, timer_handler is a function pointer * points to the function wanted to call when the timer has expired. * Return value : upon successful return, the function returns a pointer points to * the declared timer. Otherwise, return NULL. */ATIMER *timer_declare(int time_set, timer_handler *handler, void *arg);/* * Function : undeclare a timer * Parameter : a pointer points to a declared timer * Return value : returns 0 on success and -1 on error */int timer_undeclare(ATIMER *t);/* * Function : update timers * Return value : a pointer points to the timer which will expire next * or NULL if no timers. */ATIMER *timer_update();/* called when a timer has expired */void timer_out_handler(int signo);#endif/*********** timers.c *************/#include "timers.h"/* I prefer to use array instead of linked list, which is more brevity and simpler */static ATIMER apue_timers[MAX_TIMERS]; /* array of timers */static ATIMER *next_timer = NULL; /* point to the next expired timer */static volatile int time_cur = 0, time_set = 0; /* record the time */static struct sigaction act; /* new sigaction */static struct sigaction oldact; /* old sigaction */static sigset_t set, old_set;static void disable_interrupt(void){ sigfillset(&set); sigdelset(&set, SIGQUIT); sigdelset(&set, SIGALRM); if(sigprocmask(SIG_SETMASK, &set, &old_set) < 0) fprintf(stderr, "sigprocmask error\n");}static void enable_interrupt(void){ if(sigprocmask(SIG_SETMASK, &old_set, NULL) < 0) fprintf(stderr, "sigprocmask error\n");}int timer_init(void){ int i; sigset_t mask; disable_interrupt(); /* initialize timers array */ for(i = 0; i < MAX_TIMERS; i++) apue_timers[i].inuse = FALSE; /* initialize sigaction */ sigfillset(&mask); sigdelset(&mask, SIGQUIT); sigdelset(&set, SIGALRM); act.sa_mask = mask; act.sa_handler = timer_out_handler; if(sigaction(SIGALRM, &act, &oldact) < 0) { fprintf(stderr, "sigaction error\n"); enable_interrupt(); return -1; } enable_interrupt(); return 0;}void timer_cancel(void){ int i; disable_interrupt(); alarm(0); for(i = 0; i < MAX_TIMERS; i++) apue_timers[i].inuse = FALSE; /* reset sigaction */ if(sigaction(SIGALRM, &oldact, NULL) < 0) { fprintf(stderr, "sigaction error\n"); enable_interrupt(); } enable_interrupt();}ATIMER *timer_declare(int time_set, timer_handler *handler, void *arg){ ATIMER *new_timer; disable_interrupt(); /* find a timer not inuse */ for( new_timer = apue_timers; new_timer < &apue_timers[MAX_TIMERS] ; new_timer++) { if(!new_timer->inuse) break; } /* no timer available */ if(new_timer == &apue_timers[MAX_TIMERS]) { enable_interrupt(); return NULL; } /* found a timer */ new_timer->inuse = TRUE; new_timer->time_wait = time_set; new_timer->handler = handler; new_timer->arg = arg; /* update timers */ next_timer = timer_update(); /* set next timer */ if(!next_timer || new_timer->time_wait < next_timer->time_wait) { next_timer = new_timer; alarm(0); alarm(next_timer->time_wait); } enable_interrupt(); return new_timer;} int timer_undeclare(ATIMER *t){ disable_interrupt(); /* check parameter t */ if(t < apue_timers || t >= &apue_timers[MAX_TIMERS] || !t->inuse) { enable_interrupt(); return -1; } t->inuse = FALSE; /* reset alarm if t is next_timer */ if(t == next_timer) { alarm(0); next_timer = timer_update(); } enable_interrupt(); return 0;} ATIMER *timer_update(){ int decrement; int flag = FALSE; ATIMER *t; ATIMER temp_timer = { 0, VERY_LONG_TIME, NULL }; disable_interrupt(); /* update time */ if(time_set == 0) { time_set = times(NULL); decrement = 0; } else { time_cur = times(NULL); /* get decrement and convert to seconds */ decrement = (time_cur - time_set) / sysconf(_SC_CLK_TCK); /* printf("decrement = %d\n", decrement);/* !!for debug!! */ assert(decrement >= 0); /* someting may happen */ time_set = time_cur; /* reset time_set */ } /* reset next_timer */ next_timer = &temp_timer; /* update timers and get next timer */ for(t = apue_timers; t < &apue_timers[MAX_TIMERS]; t++) { if(t->inuse) { if(decrement < t->time_wait) t->time_wait -= decrement; if(t->time_wait < next_timer->time_wait) next_timer = t; flag = TRUE; } } /* reset alarm */ alarm(0); if(flag) { alarm(next_timer->time_wait); } else { next_timer = NULL; time_cur = time_set = 0; } enable_interrupt(); return next_timer;}void timer_out_handler(int signo){ /* call user hanler */ next_timer->handler(next_timer->arg); /* update timers */ next_timer->inuse = FALSE; next_timer = timer_update();}
- 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] 第四章习题解答
- 关于电脑各方面的网站
- 开发Android必备的java基础
- 新的旅程
- cross compile toolchain for arm/android
- read write 调用过程 文件读写 分析
- APUE 习题10.5 - Implementing Software Timer
- 简单搜索1979@POJ
- 地面站
- C语言的编译期行为(一) defined预处理函数
- asp.net网站中上传文件代码
- Java基础温习
- 玩转Google开源C++单元测试框架Google Test系列(gtest)(总)
- Windows编程(6)|SDK的GDI
- java与mysql乱码的问题