- 论坛徽章:
- 1
|
这是net-snmp中的代码 用setitimer和链表实现
snmp_alarm.h
- #ifndef SNMP_ALARM_H
- #define SNMP_ALARM_H
- #define RETSIGTYPE void
- typedef 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);
- #endif
复制代码
snmp_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 int
- snmp_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 int
- snmp_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()
- {
- init_alarm_post_config();
- snmp_alarm_register(5, SA_REPEAT,fun1,NULL);
- snmp_alarm_register(10, SA_REPEAT,fun2,NULL);
- for(;;){
- pause();
- }
- return 0;
- }*/
复制代码
[ 本帖最后由 yecheng_110 于 2008-10-6 23:59 编辑 ] |
|