目录
使用计时器时 ,如果在seconds秒内再次调用了alarm函数设置了新的闹钟,则后面定时器的设置将覆盖前面的设置,即之前设置的秒数被新的闹钟时间取代。以下代码主要实现使用单一计时器,实现任意数量的计时器功能。
anytime.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
#include "anytimer.h"
static int inited = 0;
static struct sigaction alrm_save;
static void at_handler(int s, siginfo_t *infop, void *a)
{
int i;
if(infop->si_code != SI_KERNEL)
return ;
for(i = 0; i < JOB_MAX; i++)
{
if(job[i] != NULL)
{
if(job[i]->sec > 0)
job[i]->sec--;
if(!(job[i]->sec) && job[i]->status == 0)
{
job[i]->status = 1;
job[i]->jobfunc(job[i]->arg);
}
}
}
}
static void module_unload(void)
{
int i;
struct itimerval tm;
sigaction(SIGALRM,&alrm_save,NULL);
tm.it_interval.tv_sec = 0;
tm.it_interval.tv_usec = 0;
tm.it_value.tv_sec = 0;
tm.it_value.tv_usec = 0;
if(setitimer(ITIMER_REAL,&tm,NULL) < 0)
return ;
for(i = 0; i < JOB_MAX; i++)
{
free(job[i]);
}
}
static int module_load(void)
{
struct itimerval tm;
struct sigaction act;
act.sa_sigaction = at_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
if(sigaction(SIGALRM,&act,&alrm_save) < 0)
return -1;
tm.it_interval.tv_sec = 1;
tm.it_interval.tv_usec = 0;
tm.it_value.tv_sec = 1;
tm.it_value.tv_usec = 0;
if(setitimer(ITIMER_REAL,&tm,NULL) < 0)
return -2;
atexit(module_unload);
return 0;
}
static int find_pos()
{
int i;
for(i = 0; i < JOB_MAX; i++)
{
if(job[i] == NULL)
return i;
}
return -1;
}
int at_addjob(int sec,at_jobfunc_t *jobp,void *arg)
{
struct at_st *me;
int pos;
char *str = arg;
if(sec <= 0)
return -EINVAL;
if(!inited)
{
module_load();
inited = 1;
}
me = malloc(sizeof(*me));
if(me == NULL)
return -ENOMEM;
if((pos = find_pos()) < 0)
{
printf("pos = %d\n",pos);
return -ENOSPC;
}
me->sec = sec;
me->jobfunc = jobp;
me->status = 0;
me->arg = arg;
job[pos] = me;
return pos;
}
int at_canceljob(int id)
{
if(id < 0 || id >= JOB_MAX)
return -EINVAL;
if(job[id]->status == 1)
return -EBUSY;
if(job[id]->status == 2)
return -ECANCELED;
job[id]->status = 2;
return 0;
}
int at_waitjob(int id)
{
while(job[id]->status != 1)
pause();
return 0;
}
anytime.h
#ifndef ANYTIMER__H_
#define ANYTIMER__H_
#define JOB_MAX 1024
typedef void at_jobfunc_t(void *);
struct at_st *job[JOB_MAX];
struct at_st
{
int sec;
at_jobfunc_t *jobfunc;
void *arg;
int status;
int pos;
};
int at_addjob(int sec,at_jobfunc_t *jobp,void *arg);
/*
*
* return >= 0 成功,返回任务ID
* == -EINVAL 失败,参数非法
* == -ENOSPC 失败,数组满
* == -ENOMEM 失败,内存空间不足
* */
int at_canceljob(int id);
/*
* return == 0 成功,指定任务成功取消
* == -EINVAL 失败,参数非法
* == -EBUSY 失败,指定任务已完成
* == -ECANCELED 失败,指定任务重复取消
* */
int at_waitjob(int id);
/*
* return == 0 成功,指定任务成功释放
* == -EINVAL 失败,参数非法
* */
#endif
main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "anytimer.h"
static void f2(void *p)
{
char *str = p;
printf("f2():%s\n",str);
}
static void f1(void *p)
{
char *str = p;
printf("f1():%s\n",str);
}
int main()
{
int job1,job2,job3;
int ret;
puts("Begin!");
job1 = at_addjob(5,f1,"aaa");
if(job1 < 0)
{
fprintf(stderr,"at_addjob():%s\n",strerror(-job1));
exit(1);
}
job2 = at_addjob(100,f2,"bbb");
if(job2 < 0)
{
fprintf(stderr,"at_addjob():%s\n",strerror(-job2));
exit(1);
}
job3 = at_addjob(500,f1,"ccc");
if(job3 < 0)
{
fprintf(stderr,"at_addjob():%s\n",strerror(-job3));
exit(1);
}
puts("End!");
ret = at_canceljob(job3);
if(ret < 0)
{
fprintf(stderr,"at_canceljob():%s\n",strerror(-ret));
exit(1);
}
//at_waitjob(job1);
while(1)
{
write(1,".",1);
sleep(1);
}
exit(0);
}
运行结果如下: