源自APUE 习题10.5
代码参考自上一篇译文博客:Implementing Software Timer。
代码由两部分组成:my_alarm.h my_alarm.c
my_alarm.h
#include <stdio.h> #include <unistd.h> #include <time.h> #include <signal.h> #define TIME time_t #define MAXALARM 255 #define MAXTIME 1000 #define FALSE 0 #define TRUE 1 typedef struct { int inuse; TIME time; time_t declare_time; }MYALARM; /*********************************/ void alarm_interrupt_handler(int); int alarm_cancle(MYALARM *); MYALARM *alarm_declare(int tm,MYALARM *t); int alarm_init(); void alarm_update(); void interrupt_enable(); void interrupt_disable();
my_alarm.c
#include "my_alarm.h" MYALARM alarms[MAXALARM]; MYALARM doom_timer = {0,0,0}; MYALARM *next_timer = &doom_timer; sigset_t oldset; sigset_t maskset; struct sigaction act,oact; /*************************************/ void alarm_interrupt_handler(int sig){ printf("%d bingo\n",next_timer->time); next_timer->inuse = FALSE; alarm_update(); } int alarm_init(){ int j; for(j=0;j<MAXALARM;j++){ alarms[j].inuse=FALSE; } sigfillset(&maskset); sigemptyset(&oldset); sigdelset(&maskset,SIGALRM); sigdelset(&maskset,SIGQUIT); act.sa_handler = alarm_interrupt_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(sigaction(SIGALRM,&act,&oact)<0){ perror("error in handle alarm"); return -1; } return 0; } int alarm_cancle(MYALARM *t){ interrupt_disable(); TIME now; time(&now); if(!t->inuse){ printf("alarm not in use,can't disable\n"); return -1; } t->inuse=FALSE; if(t == next_timer){ alarm_update(); } // printf("success cancel\n"); interrupt_enable(); return 0; } MYALARM *alarm_declare(int tm,MYALARM *t){ if(tm<0 || tm>MAXTIME){ printf("error time in alarm_declare\n"); return NULL; } MYALARM *temp; interrupt_disable(); for(t=alarms;t<&alarms[MAXALARM];t++){ if(t->inuse == FALSE) break; } if(t == &alarms[MAXALARM]){ printf("alarms is full now,please try later\n"); return NULL; } t->inuse=TRUE; t->time = (time_t)tm; time(&t->declare_time); alarm_update(); interrupt_enable(); return t; } void alarm_update(){ // printf("!\n"); MYALARM *t; TIME now; interrupt_disable(); for(t=alarms;t<&alarms[MAXALARM];t++){ if(t->inuse == TRUE){ // printf("find the first next_timer\n"); next_timer =t; break; } } if(t == &alarms[MAXALARM]){ alarm(0); // printf("just return?\n"); return ; } for(t=alarms;t<&alarms[MAXALARM];t++){ if(t->inuse == TRUE){ // printf("%d %d\n",t->time,t->declare_time); fflush(0); if((t->time + t->declare_time) <( next_timer->time + next_timer->declare_time)){ next_timer = t; // printf("refresh\n"); } } } time(&now); alarm(0); alarm(next_timer->time+next_timer->declare_time - now); interrupt_enable(); } void interrupt_disable(){ if(sigprocmask(SIG_BLOCK,&maskset,&oldset)<0) perror("error in disable interrupt"); } void interrupt_enable(){ if(sigprocmask(SIG_SETMASK,&oldset,NULL)<0) perror("error in enable interrupr"); }