源自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");
}

 

posted on 2013-05-03 14:33  CoreyGao  阅读(202)  评论(0编辑  收藏  举报