利用信号知识,实现多次任意时间调用函数
my_alarm.h文件
#ifndef __MY_ALARM_H
#define __MY_ALARM_H
//最多创建1024个任务
#define MAX 1024
//函数定义
typedef void alarm_func_t(void*);
//添加任务,成功返回任务ID,失败返回-1
int anytimer_alarm(int sec, alarm_func_t *func, void *ch);
//取消任务 成功返回0,失败返回-1;
int anytimer_destory(int id);
#endif
my_alarm.c文件
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include "my_alarm.h"
static void mouder_load(void); //模块挂载,设置时间,信号等
static void handler(int s); //信号行为
static void mouder_unload(void); //模块卸载,恢复时间,信号
static int get_pos(void); //找空闲位置
//定义任务结构体
struct func_st
{
int sec; //秒数
alarm_func_t *func; //用户自定义函数
void *ch; //函数参数
};
static struct func_st *line[MAX]; //定义1024长度的数组存储结构体地址
static int inited = 0; //设置计时器,只有当inited为0的时候才调用模块挂载函数
struct sigaction oldact; //旧的信号行为
struct itimerval olditv; //旧的时间闹钟
//添加任务,成功返回任务ID,失败返回-1
int anytimer_alarm(int sec, alarm_func_t *func, void *ch)
{
struct func_st *new;
int pos;
if(inited == 0)
{
mouder_load();
inited = 1;
}
//找空位
pos = get_pos();
if(pos < 0)
return -1;
new=malloc(sizeof(*new));
if(new == NULL)
return -1;
new -> sec = sec;
new -> func = func;
new -> ch = ch;
line[pos] = new;
return pos;
}
//取消任务 成功返回0,失败返回-1;
int anytimer_destory(int id)
{
free(line[id]);
line[id] = NULL;
}
static void mouder_load(void)
{
struct sigaction act;
struct itimerval itv;
act.sa_handler = handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGALRM, &act, &oldact);
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, &olditv);
atexit(mouder_unload); //钩子函数
}
static void handler(int s)
{
int i;
for(i=0; i<MAX; i++)
{
if (line[i] != NULL) //找不为空的数组
{
if(line[i] -> sec != 0) //当结构体的时间不等于0时,时间减少1
line[i] -> sec -= 1;
else //时间为0执行用户自定义函数,并销毁该任务,由于对外提供销毁函数,所以可以由用户调用销毁,类似父进程为子进程收尸函数wait();
{
line[i] -> func(line[i]->ch);
anytimer_destory(i);
}
}
}
}
static int get_pos(void)
{
for(int i=0; i<MAX; i++)
{
if(line[i] == NULL)
return i;
}
return -1;
}
static void mouder_unload(void)
{
sigaction(SIGALRM, &oldact, NULL);
setitimer(ITIMER_REAL, &olditv, NULL);
}
调试文件alrm_hw.c
#include <stdio.h>
#include <unistd.h>
#include "my_alarm.h"
static void any1(void *s)
{
printf("%s", (char *)s);
fflush(NULL);
}
static void any2(void *s)
{
printf("%s", (char *)s);
fflush(NULL);
}
static void any3(void *s)
{
printf("%s", (char *)s);
fflush(NULL);
}
int main(void)
{
anytimer_alarm(3, any1, "hello");
anytimer_alarm(2, any2, "world");
anytimer_alarm(5, any3, "apue");
/*
**world*hello**apue******
*/
while (1) {
write(1, "*", 1);
sleep(1);
}
return 0;
}
makefile文件
SRC = alrm_hw.o my_alarm.o
OBJ = myalarm
$(OBJ):$(SRC)
gcc -o $@ $^
clean:
rm *.o $(OBJ)
运行结果
程序运行结果