免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5107 | 回复: 2
打印 上一主题 下一主题

linux下多个定时器(net-snmp) [复制链接]

论坛徽章:
1
双子座
日期:2015-01-04 14:25:06
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-10-06 21:13 |只看该作者 |倒序浏览
这是net-snmp中的代码 用setitimer和链表实现

snmp_alarm.h

  1. #ifndef SNMP_ALARM_H
  2. #define SNMP_ALARM_H

  3. #define RETSIGTYPE void

  4. typedef void (SNMPAlarmCallback) (unsigned int clientreg, void *clientarg);

  5. /*
  6. * alarm flags
  7. */
  8. #define SA_REPEAT 0x01          /* keep repeating every X seconds */

  9. struct snmp_alarm {
  10.     struct timeval t;
  11.     unsigned int flags;
  12.     unsigned int clientreg;
  13.     struct timeval t_last;
  14.     struct timeval t_next;
  15.     void *clientarg;
  16.     SNMPAlarmCallback *thecallback;
  17.     struct snmp_alarm *next;
  18. };

  19. /*
  20. * the ones you should need
  21. */
  22. void snmp_alarm_unregister(unsigned int clientreg);
  23. void snmp_alarm_unregister_all(void);
  24. unsigned int snmp_alarm_register(unsigned int when,
  25.                                  unsigned int flags,
  26.                                  SNMPAlarmCallback * thecallback,
  27.                                  void *clientarg);

  28. unsigned int snmp_alarm_register_hr(struct timeval t,
  29.                                     unsigned int flags,
  30.                                     SNMPAlarmCallback * cb, void *cd);

  31. /*
  32. * the ones you shouldn't
  33. */
  34. int init_alarm_post_config();
  35. void sa_update_entry(struct snmp_alarm *alrm);
  36. struct snmp_alarm *sa_find_next(void);
  37. void run_alarms(void);
  38. RETSIGTYPE alarm_handler(int a);
  39. void set_an_alarm(void);
  40. int get_next_alarm_delay_time(struct timeval *delta);

  41. #endif
复制代码


snmp_alarm.c

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <signal.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <netinet/in.h>
  7. #include <string.h>

  8. #include <sys/time.h>
  9. #include <time.h>

  10. #include "snmp_alarm.h"

  11. #define SNMP_MALLOC_STRUCT(s)   (struct s *) calloc(1, sizeof(struct s))

  12. static struct snmp_alarm *thealarms = NULL;
  13. static int start_alarms = 0;
  14. static unsigned int regnum = 1;

  15. int init_alarm_post_config()
  16. {
  17.     start_alarms = 1;
  18.     set_an_alarm();
  19.     return 0;
  20. }

  21. void sa_update_entry(struct snmp_alarm *a)
  22. {
  23.     if(a->t_last.tv_sec == 0 && a->t_last.tv_usec == 0) {
  24.         struct timeval t_now;

  25.         /*
  26.          * Never been called yet, call time `t' from now.  
  27.          */
  28.         gettimeofday(&t_now, NULL);

  29.         a->t_last.tv_sec = t_now.tv_sec;
  30.         a->t_last.tv_usec = t_now.tv_usec;

  31.         a->t_next.tv_sec = t_now.tv_sec + a->t.tv_sec;
  32.         a->t_next.tv_usec = t_now.tv_usec + a->t.tv_usec;

  33.         while(a->t_next.tv_usec >= 1000000) {
  34.             a->t_next.tv_usec -= 1000000;
  35.             a->t_next.tv_sec += 1;
  36.         }
  37.     }
  38.     else if(a->t_next.tv_sec == 0 && a->t_next.tv_usec == 0) {
  39.         /*
  40.          * We've been called but not reset for the next call.  
  41.          */
  42.         if(a->flags & SA_REPEAT) {
  43.             if(a->t.tv_sec == 0 && a->t.tv_usec == 0) {
  44.                 printf("update_entry: illegal interval specified\n");
  45.                 snmp_alarm_unregister(a->clientreg);
  46.                 return;
  47.             }

  48.             a->t_next.tv_sec = a->t_last.tv_sec + a->t.tv_sec;
  49.             a->t_next.tv_usec = a->t_last.tv_usec + a->t.tv_usec;

  50.             while(a->t_next.tv_usec >= 1000000) {
  51.                 a->t_next.tv_usec -= 1000000;
  52.                 a->t_next.tv_sec += 1;
  53.             }
  54.         }
  55.         else {
  56.             /*
  57.              * Single time call, remove it.  
  58.              */
  59.             snmp_alarm_unregister(a->clientreg);
  60.         }
  61.     }
  62. }

  63. /**
  64. * This function removes the callback function from a list of registered
  65. * alarms, unregistering the alarm.
  66. *
  67. * @param clientreg is a unique unsigned integer representing a registered
  68. *        alarm which the client wants to unregister.
  69. *
  70. * @return void
  71. *
  72. * @see snmp_alarm_register
  73. * @see snmp_alarm_register_hr
  74. * @see snmp_alarm_unregister_all
  75. */
  76. void snmp_alarm_unregister(unsigned int clientreg)
  77. {
  78.     struct snmp_alarm *sa_ptr, **prevNext = &thealarms;

  79.     for(sa_ptr = thealarms;
  80.         sa_ptr != NULL && sa_ptr->clientreg != clientreg;
  81.         sa_ptr = sa_ptr->next) {
  82.         prevNext = &(sa_ptr->next);
  83.     }

  84.     if(sa_ptr != NULL) {
  85.         *prevNext = sa_ptr->next;
  86.         printf("unregistered alarm %d\n", sa_ptr->clientreg);
  87.         /*
  88.          * Note:  do not free the clientarg, its the clients responsibility
  89.          */
  90.         free(sa_ptr);
  91.     }
  92.     else {
  93.         printf("no alarm %d to unregister\n", clientreg);
  94.     }
  95. }

  96. /**
  97. * This function unregisters all alarms currently stored.
  98. *
  99. * @return void
  100. *
  101. * @see snmp_alarm_register
  102. * @see snmp_alarm_register_hr
  103. * @see snmp_alarm_unregister
  104. */
  105. void snmp_alarm_unregister_all(void)
  106. {
  107.     struct snmp_alarm *sa_ptr, *sa_tmp;

  108.     for(sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_tmp) {
  109.         sa_tmp = sa_ptr->next;
  110.         free(sa_ptr);
  111.     }
  112.     printf("ALL alarms unregistered\n");
  113.     thealarms = NULL;
  114. }

  115. struct snmp_alarm *sa_find_next(void)
  116. {
  117.     struct snmp_alarm *a, *lowest = NULL;

  118.     for(a = thealarms; a != NULL; a = a->next) {
  119.         if(lowest == NULL) {
  120.             lowest = a;
  121.         }
  122.         else if(a->t_next.tv_sec == lowest->t_next.tv_sec) {
  123.             if(a->t_next.tv_usec < lowest->t_next.tv_usec) {
  124.                 lowest = a;
  125.             }
  126.         }
  127.         else if(a->t_next.tv_sec < lowest->t_next.tv_sec) {
  128.             lowest = a;
  129.         }
  130.     }
  131.     return lowest;
  132. }

  133. struct snmp_alarm *sa_find_specific(unsigned int clientreg)
  134. {
  135.     struct snmp_alarm *sa_ptr;

  136.     for(sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_ptr->next) {
  137.         if(sa_ptr->clientreg == clientreg) {
  138.             return sa_ptr;
  139.         }
  140.     }
  141.     return NULL;
  142. }

  143. void run_alarms(void)
  144. {
  145.     int done = 0;
  146.     struct snmp_alarm *a = NULL;
  147.     unsigned int clientreg;
  148.     struct timeval t_now;

  149.     /*
  150.      * Loop through everything we have repeatedly looking for the next thing to
  151.      * call until all events are finally in the future again.  
  152.      */

  153.     while(!done) {
  154.         if((a = sa_find_next()) == NULL) {
  155.             return;
  156.         }

  157.         gettimeofday(&t_now, NULL);

  158.         if((a->t_next.tv_sec < t_now.tv_sec) ||
  159.            ((a->t_next.tv_sec == t_now.tv_sec) &&
  160.             (a->t_next.tv_usec < t_now.tv_usec))) {
  161.             clientreg = a->clientreg;
  162.             printf("run alarm %d\n", clientreg);
  163.             (*(a->thecallback)) (clientreg, a->clientarg);
  164.             printf("alarm %d completed\n", clientreg);

  165.             if((a = sa_find_specific(clientreg)) != NULL) {
  166.                 a->t_last.tv_sec = t_now.tv_sec;
  167.                 a->t_last.tv_usec = t_now.tv_usec;
  168.                 a->t_next.tv_sec = 0;
  169.                 a->t_next.tv_usec = 0;
  170.                 sa_update_entry(a);
  171.             }
  172.             else {
  173.                 printf("alarm %d deleted itself\n", clientreg);
  174.             }
  175.         }
  176.         else {
  177.             done = 1;
  178.         }
  179.     }
  180. }



  181. RETSIGTYPE alarm_handler(int a)
  182. {
  183.     run_alarms();
  184.     set_an_alarm();
  185. }



  186. int get_next_alarm_delay_time(struct timeval *delta)
  187. {
  188.     struct snmp_alarm *sa_ptr;
  189.     struct timeval t_diff, t_now;

  190.     sa_ptr = sa_find_next();

  191.     if(sa_ptr) {
  192.         gettimeofday(&t_now, 0);

  193.         if((t_now.tv_sec > sa_ptr->t_next.tv_sec) ||
  194.            ((t_now.tv_sec == sa_ptr->t_next.tv_sec) &&
  195.             (t_now.tv_usec > sa_ptr->t_next.tv_usec))) {
  196.             /*
  197.              * Time has already passed.  Return the smallest possible amount of
  198.              * time.  
  199.              */
  200.             delta->tv_sec = 0;
  201.             delta->tv_usec = 1;
  202.             return sa_ptr->clientreg;
  203.         }
  204.         else {
  205.             /*
  206.              * Time is still in the future.  
  207.              */
  208.             t_diff.tv_sec = sa_ptr->t_next.tv_sec - t_now.tv_sec;
  209.             t_diff.tv_usec = sa_ptr->t_next.tv_usec - t_now.tv_usec;

  210.             while(t_diff.tv_usec < 0) {
  211.                 t_diff.tv_sec -= 1;
  212.                 t_diff.tv_usec += 1000000;
  213.             }

  214.             delta->tv_sec = t_diff.tv_sec;
  215.             delta->tv_usec = t_diff.tv_usec;
  216.             return sa_ptr->clientreg;
  217.         }
  218.     }

  219.     /*
  220.      * Nothing Left.  
  221.      */
  222.     return 0;
  223. }


  224. void set_an_alarm(void)
  225. {
  226.     struct timeval delta;
  227.     int nextalarm = get_next_alarm_delay_time(&delta);

  228.     /*
  229.      * We don't use signals if they asked us nicely not to.  It's expected
  230.      * they'll check the next alarm time and do their own calling of
  231.      * run_alarms().  
  232.      */

  233.     if(nextalarm) {
  234.         struct itimerval it;

  235.         it.it_value.tv_sec = delta.tv_sec;
  236.         it.it_value.tv_usec = delta.tv_usec;
  237.         it.it_interval.tv_sec = 0;
  238.         it.it_interval.tv_usec = 0;

  239.         signal(SIGALRM, alarm_handler);
  240.         setitimer(ITIMER_REAL, &it, NULL);
  241.         printf("schedule alarm %d in %d.%03d seconds\n",
  242.                nextalarm, (int) delta.tv_sec,
  243.                (int) (delta.tv_usec / 1000));

  244.     }
  245.     else {
  246.         printf("no alarms found to schedule\n");
  247.     }
  248. }


  249. /**
  250. * This function registers function callbacks to occur at a speciifc time
  251. * in the future.
  252. *
  253. * @param when is an unsigned integer specifying when the callback function
  254. *             will be called in seconds.
  255. *
  256. * @param flags is an unsigned integer that specifies how frequent the callback
  257. *        function is called in seconds.  Should be SA_REPEAT or 0.  If  
  258. *        flags  is  set with SA_REPEAT, then the registered callback function
  259. *        will be called every SA_REPEAT seconds.  If flags is 0 then the
  260. *        function will only be called once and then removed from the
  261. *        registered alarm list.
  262. *
  263. * @param thecallback is a pointer SNMPAlarmCallback which is the callback
  264. *        function being stored and registered.
  265. *
  266. * @param clientarg is a void pointer used by the callback function.  This
  267. *        pointer is assigned to snmp_alarm->clientarg and passed into the
  268. *        callback function for the client's specifc needs.
  269. *
  270. * @return Returns a unique unsigned integer(which is also passed as the first
  271. *        argument of each callback), which can then be used to remove the
  272. *        callback from the list at a later point in the future using the
  273. *        snmp_alarm_unregister() function.  If memory could not be allocated
  274. *        for the snmp_alarm struct 0 is returned.
  275. *
  276. * @see snmp_alarm_unregister
  277. * @see snmp_alarm_register_hr
  278. * @see snmp_alarm_unregister_all
  279. */
  280. unsigned int
  281. snmp_alarm_register(unsigned int when, unsigned int flags,
  282.                     SNMPAlarmCallback * thecallback, void *clientarg)
  283. {
  284.     struct snmp_alarm **sa_pptr;

  285.     if(thealarms != NULL) {
  286.         for(sa_pptr = &thealarms; (*sa_pptr) != NULL;
  287.             sa_pptr = &((*sa_pptr)->next)) ;
  288.     }
  289.     else {
  290.         sa_pptr = &thealarms;
  291.     }

  292.     *sa_pptr = SNMP_MALLOC_STRUCT(snmp_alarm);
  293.     if(*sa_pptr == NULL)
  294.         return 0;

  295.     if(0 == when) {
  296.         (*sa_pptr)->t.tv_sec = 0;
  297.         (*sa_pptr)->t.tv_usec = 1;
  298.     }
  299.     else {
  300.         (*sa_pptr)->t.tv_sec = when;
  301.         (*sa_pptr)->t.tv_usec = 0;
  302.     }
  303.     (*sa_pptr)->flags = flags;
  304.     (*sa_pptr)->clientarg = clientarg;
  305.     (*sa_pptr)->thecallback = thecallback;
  306.     (*sa_pptr)->clientreg = regnum++;
  307.     (*sa_pptr)->next = NULL;
  308.     sa_update_entry(*sa_pptr);

  309.     printf("registered alarm %d, t = %d.%03d, flags=0x%02x\n",
  310.            (*sa_pptr)->clientreg, (int) (*sa_pptr)->t.tv_sec,
  311.            (int) ((*sa_pptr)->t.tv_usec / 1000), (*sa_pptr)->flags);

  312.     if(start_alarms){
  313.         set_an_alarm();
  314.     }

  315.     return (*sa_pptr)->clientreg;
  316. }


  317. /**
  318. * This function offers finer granularity as to when the callback
  319. * function is called by making use of t->tv_usec value forming the
  320. * "when" aspect of snmp_alarm_register().
  321. *
  322. * @param t is a timeval structure used to specify when the callback
  323. *        function(alarm) will be called.  Adds the ability to specify
  324. *        microseconds.  t.tv_sec and t.tv_usec are assigned
  325. *        to snmp_alarm->tv_sec and snmp_alarm->tv_usec respectively internally.
  326. *        The snmp_alarm_register function only assigns seconds(it's when
  327. *        argument).
  328. *
  329. * @param flags is an unsigned integer that specifies how frequent the callback
  330. *        function is called in seconds.  Should be SA_REPEAT or NULL.  If  
  331. *        flags  is  set with SA_REPEAT, then the registered callback function
  332. *        will be called every SA_REPEAT seconds.  If flags is NULL then the
  333. *        function will only be called once and then removed from the
  334. *        registered alarm list.
  335. *
  336. * @param cb is a pointer SNMPAlarmCallback which is the callback
  337. *        function being stored and registered.
  338. *
  339. * @param cd is a void pointer used by the callback function.  This
  340. *        pointer is assigned to snmp_alarm->clientarg and passed into the
  341. *        callback function for the client's specifc needs.
  342. *
  343. * @return Returns a unique unsigned integer(which is also passed as the first
  344. *        argument of each callback), which can then be used to remove the
  345. *        callback from the list at a later point in the future using the
  346. *        snmp_alarm_unregister() function.  If memory could not be allocated
  347. *        for the snmp_alarm struct 0 is returned.
  348. *
  349. * @see snmp_alarm_register
  350. * @see snmp_alarm_unregister
  351. * @see snmp_alarm_unregister_all
  352. */
  353. unsigned int
  354. snmp_alarm_register_hr(struct timeval t, unsigned int flags,
  355.                        SNMPAlarmCallback * cb, void *cd)
  356. {
  357.     struct snmp_alarm **s = NULL;

  358.     for(s = &(thealarms); *s != NULL; s = &((*s)->next)) ;

  359.     *s = SNMP_MALLOC_STRUCT(snmp_alarm);
  360.     if(*s == NULL) {
  361.         return 0;
  362.     }

  363.     (*s)->t.tv_sec = t.tv_sec;
  364.     (*s)->t.tv_usec = t.tv_usec;
  365.     (*s)->flags = flags;
  366.     (*s)->clientarg = cd;
  367.     (*s)->thecallback = cb;
  368.     (*s)->clientreg = regnum++;
  369.     (*s)->next = NULL;

  370.     sa_update_entry(*s);

  371.     printf("registered alarm %d, t = %d.%03d, flags=0x%02x\n",
  372.            (*s)->clientreg, (int) (*s)->t.tv_sec,
  373.            (int) ((*s)->t.tv_usec / 1000), (*s)->flags);

  374.     if(start_alarms) {
  375.         set_an_alarm();
  376.     }

  377.     return (*s)->clientreg;
  378. }

  379. /**  @} */

  380. void fun1(unsigned int clientreg, void *clientarg)
  381. {
  382.     fprintf(stderr,"fun:%s clientreg:%d\n",__FUNCTION__,clientreg);
  383. }

  384. void fun2(unsigned int clientreg, void *clientarg)
  385. {
  386.     fprintf(stderr,"fun:%s clientreg:%d\n",__FUNCTION__,clientreg);
  387. }


  388. //使用示例 很简单
  389. /*int main()
  390. {
  391.     init_alarm_post_config();
  392.     snmp_alarm_register(5, SA_REPEAT,fun1,NULL);
  393.     snmp_alarm_register(10, SA_REPEAT,fun2,NULL);
  394.     for(;;){
  395.         pause();
  396.     }
  397.     return 0;
  398. }*/

复制代码

[ 本帖最后由 yecheng_110 于 2008-10-6 23:59 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-10-06 23:52 |只看该作者
很有借鉴意义,不少项目中的定时器应该都是这样实现的

论坛徽章:
0
3 [报告]
发表于 2008-10-07 00:45 |只看该作者
lighttpd里面也是类似的实现,我自己写了一个定时器模块也是采用的settimer...
http://www.cppblog.com/converse/archive/2008/08/13/58731.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP