用c语言编写定时器程序,C语言实现任务调度与定时器

scheduler.c

/*

* Layer Two Tunnelling Protocol Daemon

* Copyright (C) 1998 Adtran, Inc.

* Copyright (C) 2002 Jeff McAdams

*

* Mark Spencer

*

* This software is distributed under the terms

* of the GPL, which you should have received

* along with this source.

*

* Scheduler code for time based functionality

*

*/

#include

#include

#include

#include

#include "scheduler.h"

struct schedule_entry *events;

static struct timeval zero;

static sigset_t alarm;

/*

init_scheduler配合schedule_lock,schedule_unlock使用,用来屏蔽当前进程中特定协议的处理

*/

void init_scheduler (void)/*初始化了两个不同的信号集*/

{

struct sigaction act;

act.sa_handler = alarm_handler;/*alarm信号执行体*/

#if defined (LINUX) && (__i386__)

act.sa_restorer = NULL;

#endif

act.sa_flags = 0;

sigemptyset (&act.sa_mask);

sigaddset (&act.sa_mask, SIGALRM);/*将SIGALRM信号添加到信号集sa_mask中,SIGALRM信号会阻塞*/

sigaction (SIGALRM, &act, NULL);/*安装登记信号*/

events = NULL;

zero.tv_usec = 0;

zero.tv_sec = 0;

sigemptyset (&alarm);

sigaddset (&alarm, SIGALRM);/*将SIGALRM信号添加到信号集alarm中,SIGALRM信号会阻塞*/

}

void alarm_handler (int signal)

{

/* Check queue for events which should be

executed right now. Execute them, then

see how long we should set the next timer

*/

struct schedule_entry *p = events;

struct timeval now;

struct timeval then;

struct itimerval itv;

static int cnt = 0;

cnt++;

if (cnt != 1)

{

/* Whoa, we got called from within ourselves! */

//log (LOG_DEBUG, "%s : Whoa... cnt = %d\n", __FUNCTION__, cnt);

return;

}

while (events)

{

gettimeofday (&now, NULL);

p = events;

if (TVLESSEQ (p->tv, now))

{

events = events->next;

/* This needs to be executed, as it has expired.

It is expected that p->func will free p->data

if it is necessary */

(*p->func) (p->data);

free (p);

}

else

break;

}

/* When we get here, either there are no more events

in the queue, or the remaining events need to happen

in the future, so we should schedule another alarm */

if (events)

{

then.tv_sec = events->tv.tv_sec - now.tv_sec;

then.tv_usec = events->tv.tv_usec - now.tv_usec;

if (then.tv_usec < 0)

{

then.tv_sec -= 1;

then.tv_usec += 1000000;

}

if ((then.tv_sec <= 0) && (then.tv_usec <= 0))

{

//log (LOG_WARN, "%s: Whoa... Scheduling for <=0 time???\n",__FUNCTION__);

}

else

{

itv.it_interval = zero;

itv.it_value = then;

setitimer (ITIMER_REAL, &itv, NULL);/*重新定时,时间到后发送SIGALRM信号*/

}

}

cnt--;

}

void schedule_lock ()/*将alarm添加到当前进程阻塞信号集中,信号来时会被阻塞,暂时捕获不到,移除后会捕获?/

{

while (sigprocmask (SIG_BLOCK, &alarm, NULL));

};

void schedule_unlock ()/*将alarm从当前进程阻塞信号集中移除*/

{

/* See if we missed any events */

/*alarm_handler(0); */

while (sigprocmask (SIG_UNBLOCK, &alarm, NULL));

raise (SIGALRM);/*用来向本进程发送信号*/

};

struct schedule_entry *schedule (struct timeval tv, void (*func) (void *),

void *data)

{

/* Schedule func to be run at relative time tv with data

as arguments. If it has already expired, run it

immediately. The queue should be in order of

increasing time */

struct schedule_entry *p = events, *q = NULL; /*时间间隔递增的队列*/

int need_timer = 0;

struct timeval diff;

struct itimerval itv;/*队列中越靠前,越早发生*/

diff = tv;

gettimeofday (&tv, NULL);

tv.tv_sec += diff.tv_sec; /*转换为本地系统时间*/

tv.tv_usec += diff.tv_usec;

if (tv.tv_usec > 1000000)

{

tv.tv_sec++;

tv.tv_usec -= 1000000;/*进制转换*/

}

while (p)

{

if (TVLESS (tv, p->tv)) /*tv < p->tv*/

break;

q = p;

p = p->next;

};

if (q)

{

q->next =

(struct schedule_entry *) malloc (sizeof (struct schedule_entry));

q = q->next;

}

else

{/*时间比队列中的第一个时间还小*/

q = (struct schedule_entry *) malloc (sizeof (struct schedule_entry));

events = q;

need_timer = -1;

}

q->tv = tv;

q->func = func;

q->data = data;

q->next = p;

if (need_timer)

{

itv.it_interval = zero;

itv.it_value = diff;

setitimer (ITIMER_REAL, &itv, NULL); /*重新修改定时*/

}

return q;

}

inline struct schedule_entry *aschedule (struct timeval tv,/*tv传递的为绝对时间*/

void (*func) (void *), void *data)

{

/* Schedule func to be run at absolute time tv in the future with data

as arguments */

struct timeval now;

gettimeofday (&now, NULL);

tv.tv_usec -= now.tv_usec;

if (tv.tv_usec < 0)

{

tv.tv_usec += 1000000;

tv.tv_sec--;

}

tv.tv_sec -= now.tv_sec;

return schedule (tv, func, data);

}

void deschedule (struct schedule_entry *s)/*取消任务*/

{

struct schedule_entry *p = events, *q = NULL;

if (!s)

return;

while (p)

{

if (p == s)

{

if (q)

{

q->next = p->next;

}

else

{

events = events->next;

}

free (p);

break;

}

q = p;

p = p->next;

}

}

scheduler.h

/*

* * Layer Two Tunnelling Protocol Daemon

* * Copyright (C) 1998 Adtran, Inc.

* * Copyright (C) 2002 Jeff McAdams

* *

* * Mark Spencer

* *

* * This software is distributed under the terms

* * of the GPL, which you should have received

* * along with this source.

* *

* * Scheduler structures and functions

* *

* */

#ifndef _SCHEDULER_H

#define _SCHEDULER_H

#include

/*

* * The idea is to provide a general scheduler which can schedule

* * events to be run periodically

* */

struct schedule_entry

{

struct timeval tv; /* Scheduled time to execute */

void (*func) (void *); /* Function to execute */

void *data; /* Data to be passed to func */

struct schedule_entry *next; /* Next entry in queue */

};

extern struct schedule_entry *events;

/* Schedule func to be executed with argument data sometime

* tv in the future. */

struct schedule_entry *schedule (struct timeval tv, void (*func) (void *),

void *data);

/* Like schedule() but tv represents an absolute time in the future */

struct schedule_entry *aschedule (struct timeval tv, void (*func) (void *),

void *data);

/* Remove a scheduled event from the queue */

void deschedule (struct schedule_entry *);

/* The alarm handler */

void alarm_handler (int);

/* Initialization function */

void init_scheduler (void);

/* Prevent the scheduler from running */

void schedule_lock ();

/* Restore normal scheduling functions */

void schedule_unlock ();

/* Compare two timeval functions and see if a <= b */

#define TVLESS(a,b) ((a).tv_sec == (b).tv_sec ? \

((a).tv_usec < (b).tv_usec) : \

((a).tv_sec < (b).tv_sec))

#define TVLESSEQ(a,b) ((a).tv_sec == (b).tv_sec ? \

((a).tv_usec <= (b).tv_usec) : \

((a).tv_sec <= (b).tv_sec))

#define TVGT(a,b) ((a).tv_sec == (b).tv_sec ? \

((a).tv_usec > (b).tv_usec) : \

((a).tv_sec > (b).tv_sec))

#endif

scheduler_test.h

#include

#include

#include

#include

#include

#include "scheduler.h"

struct schedule_entry *events;

static struct timeval zero;

static sigset_t alarm;

/*****************************************************************/

void func_test(void *data)

{

struct timeval tv;

tv.tv_sec = 5;

tv.tv_usec = 0;

time_t ltime;

struct timeval ptv;

struct tm *ptm;

char printdatetime[64] = {0};

ltime = time(&ltime);

ptm = localtime(&ltime);

strftime(printdatetime, sizeof(printdatetime), "%Y-%m-%d %H:%M:%S", ptm);

gettimeofday(&ptv, NULL);

printf("%s --> [ %d : %d ] --> 落霞与孤鹜齐飞,秋水共长天一色\n", printdatetime, ptv.tv_sec, ptv.tv_usec);

schedule(tv, func_test, NULL);

}

void main(int argc, char *argv[])

{

struct timeval tv;

struct timeval timeout;

printf("------scheduler-------\n");

init_scheduler ();

tv.tv_sec = 5;

tv.tv_usec = 0;

schedule(tv, func_test, NULL);

timeout.tv_sec = 1;

timeout.tv_usec = 0;

while(1){

select(0,NULL,NULL,NULL, &timeout);

}

}

编译:

gcc -o scheduler scheduler_test.c scheduler.c scheduler.h

结果:

b5eee369da3fdf6354b1d9af97cc115a.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值