APUE习题10.5之implementing software timer

题目:仅使用一个定时器,构造一组函数,使得进程在该单一定时器基础上可以设置任意数量的定时器。

具体思路请见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 use

	TIME time; // relative time to wait

	timer_handler *ahandler; // called when the timer has expired

	void *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);

	}else

		timer_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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值