用户态下多定时器的实现
来源:互联网 发布:手机自动打开数据连接 编辑:程序博客网 时间:2024/06/05 10:02
参考书《网络编程与分层协议设计基于Linux平台实现》ISBN 978-7-111-35052-1
用链表实现多个定时器
snmp_aparm.h
#ifndef SNMP_ALARM_H#define SNMP_ALARM_H#define RETSIGTYPE voidtypedef void (SNMPAlarmCallback) (unsigned int clientreg, void *clientarg);/* * alarm flags */#define SA_REPEAT 0x01 /* keep repeating every X seconds */struct snmp_alarm { struct timeval t; unsigned int flags; unsigned int clientreg; struct timeval t_last; struct timeval t_next; void *clientarg; SNMPAlarmCallback *thecallback; struct snmp_alarm *next;};/* * the ones you should need */void snmp_alarm_unregister(unsigned int clientreg);void snmp_alarm_unregister_all(void);unsigned int snmp_alarm_register(unsigned int when, unsigned int flags, SNMPAlarmCallback * thecallback, void *clientarg);unsigned int snmp_alarm_register_hr(struct timeval t, unsigned int flags, SNMPAlarmCallback * cb, void *cd);/* * the ones you shouldn't */int init_alarm_post_config();void sa_update_entry(struct snmp_alarm *alrm);struct snmp_alarm *sa_find_next(void);void run_alarms(void);RETSIGTYPE alarm_handler(int a);void set_an_alarm(void);int get_next_alarm_delay_time(struct timeval *delta);#endifsnmp_alarm.c
#include <stdio.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <sys/types.h>#include <netinet/in.h>#include <string.h>#include <sys/time.h>#include <time.h>#include "snmp_alarm.h"#define SNMP_MALLOC_STRUCT(s) (struct s *) calloc(1, sizeof(struct s))static struct snmp_alarm *thealarms = NULL;static int start_alarms = 0;static unsigned int regnum = 1;int init_alarm_post_config(){ start_alarms = 1; set_an_alarm(); return 0;}void sa_update_entry(struct snmp_alarm *a){ if(a->t_last.tv_sec == 0 && a->t_last.tv_usec == 0) { struct timeval t_now; /* * Never been called yet, call time `t' from now. */ gettimeofday(&t_now, NULL); a->t_last.tv_sec = t_now.tv_sec; a->t_last.tv_usec = t_now.tv_usec; a->t_next.tv_sec = t_now.tv_sec + a->t.tv_sec; a->t_next.tv_usec = t_now.tv_usec + a->t.tv_usec; while(a->t_next.tv_usec >= 1000000) { a->t_next.tv_usec -= 1000000; a->t_next.tv_sec += 1; } } else if(a->t_next.tv_sec == 0 && a->t_next.tv_usec == 0) { /* * We've been called but not reset for the next call. */ if(a->flags & SA_REPEAT) { if(a->t.tv_sec == 0 && a->t.tv_usec == 0) { printf("update_entry: illegal interval specified\n"); snmp_alarm_unregister(a->clientreg); return; } a->t_next.tv_sec = a->t_last.tv_sec + a->t.tv_sec; a->t_next.tv_usec = a->t_last.tv_usec + a->t.tv_usec; while(a->t_next.tv_usec >= 1000000) { a->t_next.tv_usec -= 1000000; a->t_next.tv_sec += 1; } } else { /* * Single time call, remove it. */ snmp_alarm_unregister(a->clientreg); } }}/** * This function removes the callback function from a list of registered * alarms, unregistering the alarm. * * @param clientreg is a unique unsigned integer representing a registered * alarm which the client wants to unregister. * * @return void * * @see snmp_alarm_register * @see snmp_alarm_register_hr * @see snmp_alarm_unregister_all */void snmp_alarm_unregister(unsigned int clientreg){ struct snmp_alarm *sa_ptr, **prevNext = &thealarms; for(sa_ptr = thealarms; sa_ptr != NULL && sa_ptr->clientreg != clientreg; sa_ptr = sa_ptr->next) { prevNext = &(sa_ptr->next); } if(sa_ptr != NULL) { *prevNext = sa_ptr->next; printf("unregistered alarm %d\n", sa_ptr->clientreg); /* * Note: do not free the clientarg, its the clients responsibility */ free(sa_ptr); } else { printf("no alarm %d to unregister\n", clientreg); }}/** * This function unregisters all alarms currently stored. * * @return void * * @see snmp_alarm_register * @see snmp_alarm_register_hr * @see snmp_alarm_unregister */void snmp_alarm_unregister_all(void){ struct snmp_alarm *sa_ptr, *sa_tmp; for(sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_tmp) { sa_tmp = sa_ptr->next; free(sa_ptr); } printf("ALL alarms unregistered\n"); thealarms = NULL;}struct snmp_alarm *sa_find_next(void){ struct snmp_alarm *a, *lowest = NULL; for(a = thealarms; a != NULL; a = a->next) { if(lowest == NULL) { lowest = a; } else if(a->t_next.tv_sec == lowest->t_next.tv_sec) { if(a->t_next.tv_usec < lowest->t_next.tv_usec) { lowest = a; } } else if(a->t_next.tv_sec < lowest->t_next.tv_sec) { lowest = a; } } return lowest;}struct snmp_alarm *sa_find_specific(unsigned int clientreg){ struct snmp_alarm *sa_ptr; for(sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_ptr->next) { if(sa_ptr->clientreg == clientreg) { return sa_ptr; } } return NULL;}void run_alarms(void){ int done = 0; struct snmp_alarm *a = NULL; unsigned int clientreg; struct timeval t_now; /* * Loop through everything we have repeatedly looking for the next thing to * call until all events are finally in the future again. */ while(!done) { if((a = sa_find_next()) == NULL) { return; } gettimeofday(&t_now, NULL); if((a->t_next.tv_sec < t_now.tv_sec) || ((a->t_next.tv_sec == t_now.tv_sec) && (a->t_next.tv_usec < t_now.tv_usec))) { clientreg = a->clientreg; printf("run alarm %d\n", clientreg); (*(a->thecallback)) (clientreg, a->clientarg); printf("alarm %d completed\n", clientreg); if((a = sa_find_specific(clientreg)) != NULL) { a->t_last.tv_sec = t_now.tv_sec; a->t_last.tv_usec = t_now.tv_usec; a->t_next.tv_sec = 0; a->t_next.tv_usec = 0; sa_update_entry(a); } else { printf("alarm %d deleted itself\n", clientreg); } } else { done = 1; } }}RETSIGTYPE alarm_handler(int a){ run_alarms(); set_an_alarm();}int get_next_alarm_delay_time(struct timeval *delta){ struct snmp_alarm *sa_ptr; struct timeval t_diff, t_now; sa_ptr = sa_find_next(); if(sa_ptr) { gettimeofday(&t_now, 0); if((t_now.tv_sec > sa_ptr->t_next.tv_sec) || ((t_now.tv_sec == sa_ptr->t_next.tv_sec) && (t_now.tv_usec > sa_ptr->t_next.tv_usec))) { /* * Time has already passed. Return the smallest possible amount of * time. */ delta->tv_sec = 0; delta->tv_usec = 1; return sa_ptr->clientreg; } else { /* * Time is still in the future. */ t_diff.tv_sec = sa_ptr->t_next.tv_sec - t_now.tv_sec; t_diff.tv_usec = sa_ptr->t_next.tv_usec - t_now.tv_usec; while(t_diff.tv_usec < 0) { t_diff.tv_sec -= 1; t_diff.tv_usec += 1000000; } delta->tv_sec = t_diff.tv_sec; delta->tv_usec = t_diff.tv_usec; return sa_ptr->clientreg; } } /* * Nothing Left. */ return 0;}void set_an_alarm(void){ struct timeval delta; int nextalarm = get_next_alarm_delay_time(&delta); /* * We don't use signals if they asked us nicely not to. It's expected * they'll check the next alarm time and do their own calling of * run_alarms(). */ if(nextalarm) { struct itimerval it; it.it_value.tv_sec = delta.tv_sec; it.it_value.tv_usec = delta.tv_usec; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 0; signal(SIGALRM, alarm_handler); setitimer(ITIMER_REAL, &it, NULL); printf("schedule alarm %d in %d.%03d seconds\n", nextalarm, (int) delta.tv_sec, (int) (delta.tv_usec / 1000)); } else { printf("no alarms found to schedule\n"); }}/** * This function registers function callbacks to occur at a speciifc time * in the future. * * @param when is an unsigned integer specifying when the callback function * will be called in seconds. * * @param flags is an unsigned integer that specifies how frequent the callback * function is called in seconds. Should be SA_REPEAT or 0. If * flags is set with SA_REPEAT, then the registered callback function * will be called every SA_REPEAT seconds. If flags is 0 then the * function will only be called once and then removed from the * registered alarm list. * * @param thecallback is a pointer SNMPAlarmCallback which is the callback * function being stored and registered. * * @param clientarg is a void pointer used by the callback function. This * pointer is assigned to snmp_alarm->clientarg and passed into the * callback function for the client's specifc needs. * * @return Returns a unique unsigned integer(which is also passed as the first * argument of each callback), which can then be used to remove the * callback from the list at a later point in the future using the * snmp_alarm_unregister() function. If memory could not be allocated * for the snmp_alarm struct 0 is returned. * * @see snmp_alarm_unregister * @see snmp_alarm_register_hr * @see snmp_alarm_unregister_all */unsigned intsnmp_alarm_register(unsigned int when, unsigned int flags, SNMPAlarmCallback * thecallback, void *clientarg){ struct snmp_alarm **sa_pptr; if(thealarms != NULL) { for(sa_pptr = &thealarms; (*sa_pptr) != NULL; sa_pptr = &((*sa_pptr)->next)) ; } else { sa_pptr = &thealarms; } *sa_pptr = SNMP_MALLOC_STRUCT(snmp_alarm); if(*sa_pptr == NULL) return 0; if(0 == when) { (*sa_pptr)->t.tv_sec = 0; (*sa_pptr)->t.tv_usec = 1; } else { (*sa_pptr)->t.tv_sec = when; (*sa_pptr)->t.tv_usec = 0; } (*sa_pptr)->flags = flags; (*sa_pptr)->clientarg = clientarg; (*sa_pptr)->thecallback = thecallback; (*sa_pptr)->clientreg = regnum++; (*sa_pptr)->next = NULL; sa_update_entry(*sa_pptr); printf("registered alarm %d, t = %d.%03d, flags=0x%02x\n", (*sa_pptr)->clientreg, (int) (*sa_pptr)->t.tv_sec, (int) ((*sa_pptr)->t.tv_usec / 1000), (*sa_pptr)->flags); if(start_alarms){ set_an_alarm(); } return (*sa_pptr)->clientreg;}/** * This function offers finer granularity as to when the callback * function is called by making use of t->tv_usec value forming the * "when" aspect of snmp_alarm_register(). * * @param t is a timeval structure used to specify when the callback * function(alarm) will be called. Adds the ability to specify * microseconds. t.tv_sec and t.tv_usec are assigned * to snmp_alarm->tv_sec and snmp_alarm->tv_usec respectively internally. * The snmp_alarm_register function only assigns seconds(it's when * argument). * * @param flags is an unsigned integer that specifies how frequent the callback * function is called in seconds. Should be SA_REPEAT or NULL. If * flags is set with SA_REPEAT, then the registered callback function * will be called every SA_REPEAT seconds. If flags is NULL then the * function will only be called once and then removed from the * registered alarm list. * * @param cb is a pointer SNMPAlarmCallback which is the callback * function being stored and registered. * * @param cd is a void pointer used by the callback function. This * pointer is assigned to snmp_alarm->clientarg and passed into the * callback function for the client's specifc needs. * * @return Returns a unique unsigned integer(which is also passed as the first * argument of each callback), which can then be used to remove the * callback from the list at a later point in the future using the * snmp_alarm_unregister() function. If memory could not be allocated * for the snmp_alarm struct 0 is returned. * * @see snmp_alarm_register * @see snmp_alarm_unregister * @see snmp_alarm_unregister_all */unsigned intsnmp_alarm_register_hr(struct timeval t, unsigned int flags, SNMPAlarmCallback * cb, void *cd){ struct snmp_alarm **s = NULL; for(s = &(thealarms); *s != NULL; s = &((*s)->next)) ; *s = SNMP_MALLOC_STRUCT(snmp_alarm); if(*s == NULL) { return 0; } (*s)->t.tv_sec = t.tv_sec; (*s)->t.tv_usec = t.tv_usec; (*s)->flags = flags; (*s)->clientarg = cd; (*s)->thecallback = cb; (*s)->clientreg = regnum++; (*s)->next = NULL; sa_update_entry(*s); printf("registered alarm %d, t = %d.%03d, flags=0x%02x\n", (*s)->clientreg, (int) (*s)->t.tv_sec, (int) ((*s)->t.tv_usec / 1000), (*s)->flags); if(start_alarms) { set_an_alarm(); } return (*s)->clientreg;}/** @} */void fun1(unsigned int clientreg, void *clientarg){ fprintf(stderr,"fun:%s clientreg:%d\n",__FUNCTION__,clientreg);}void fun2(unsigned int clientreg, void *clientarg){ fprintf(stderr,"fun:%s clientreg:%d\n",__FUNCTION__,clientreg);}//使用示例 很简单int main(){ start_alarms=1;set_an_alarm(); snmp_alarm_register(1, SA_REPEAT,fun1,NULL); snmp_alarm_register(5, SA_REPEAT,fun2,NULL); for(;;){ pause(); } return 0;}
- 用户态下多定时器的实现
- Linux 用户下定时器的实现
- 等待定时器与用户定时器的区别
- 编写一个程序库,实现定时器的功能,它能为用户提供在同一进程中多次使用的定时器。
- Linux定时器的实现
- php定时器的实现
- 定时器的实现
- servlet定时器的实现
- iphone 定时器的实现
- 定时器(Timer)的实现
- 经典定时器的实现
- Linux定时器的实现
- swt定时器的实现
- android 定时器的实现
- android定时器的实现
- android 定时器的实现
- 多定时器的实现
- 定时器Timer的实现
- 浏览器工作原理拆解分析 .
- Windows------安装JDK1.7、Tomcat7.0
- oracle常用sql
- Nivoslider:丰富的图片切换效果
- Mac下Eclipse工程路径如有中文会无法执行
- 用户态下多定时器的实现
- allowClearUserData
- 小背叛的伤感经典QQ日志发布:幸福,只是我,太天真
- Microsoft Web Application Stress Tool(WAST)详细设置说明
- 什么技术和应用赚钱?
- 看懒虫的生活
- 茉莉花的伤感日志发布:放弃也是一种美丽
- 我拒绝用ToDo列表(作者:StackOverFlow创始人Jeff Atwood)
- 看懂信息检索和网络数据挖掘领域论文的必备知识总结