Linux定时器

内核定时器:
定时触发定时器中断,执行定时器中断处理函数 <linux/timer.h>
定时器数据类型是:
struct timer_list {
unsigned long expires; //定时器计数时间值
void (*function)(unsigned long); //定时器处理函数
unsigned long data; //私有数据 };

/定义并初始化定时器/ #define DEFINE_TIMER(_name, _function, _expires, _data) \ struct timer_list _name = { \ .entry = { .prev = TIMER_ENTRY_STATIC }, \ .function = (_function), \ .expires = (_expires), \ .data = (_data), \ .base = &boot_tvec_bases, \ .slack = -1, \ __TIMER_LOCKDEP_MAP_INITIALIZER( \ FILE “:” __stringify(LINE)) \ }

内核中使用jiffies进行时间计数,计数的频率由HZ来决定
如果expires的值和jiffies值相等,就会触发定时器中断
expires = jiffies + HZ; //定时多长时间? 定时1Sexpires = jiffies + n*HZ //定时n秒
init_timer(struct timer_list * timer) //初始化定时器的函数宏
void add_timer(struct timer_list *timer); //添加定时器int del_timer(struct timer_list * timer); //删除定时器
修改定时器时间,再次触发定时器中断
int mod_timer(struct timer_list *timer, unsigned long expires);功能:修改定时器时间参数: @timer 定时器结构体指针 @expires 定时器定时时间

在2.4版本内核下用链表和信号实现定时器

1. setitimer 的原型
#include <sys/time.h>   int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
setitimer 能够在 Timer 到期之后,自动再次启动自己,因此,用它来解决 Single-Shot Timer 和 Repeating Timer 的问题显得很简单。该函数可以工作于 3 种模式:ITIMER_REAL    以实时时间 (real time) 递减,在到期之后发送 SIGALRM 信号ITIMER_VIRTUAL 仅进程在用户空间执行时递减,在到期之后发送 SIGVTALRM 信号ITIMER_PROF    进程在用户空间执行以及内核为该进程服务时 ( 典型如完成一个系统调用 ) 都会递减,与 ITIMER_VIRTUAL 共用时可度量该应用在内核空间和用户空间的时间消耗情况,在到期之后发送 SIGPROF 信号

2. setitimer 定时器的值定义
struct itimerval {  struct timeval it_interval; /* next value */  struct timeval it_value;     /* current value */  };   struct timeval {         long tv_sec;                /* seconds */         long tv_usec;               /* microseconds */  };
setitimer() 以 new_value 设置特定的定时器,如果 old_value 非空,则它返回 which 类型时间间隔定时器的前一个值。定时器从 it_value 递减到零,然后产生一个信号,并重新设置为 it_interval,如果此时 it_interval 为零,则该定时器停止。任何时候,只要 it_value 设置为零,该定时器就会停止。由于 setitimer() 不支持在同一进程中同时使用多次以支持多个定时器,因此,如果需要同时支持多个定时实例的话,需要由实现者来管理所有的实例。用 setitimer() 和链表,可以构造一个在进程环境下支持多个定时器实例的 Timer,在一般的实现中的 PerTickBookkeeping 时,会递增每个定时器的 elapse 值,直到该值递增到最初设定的 interval 则表示定时器到期。

3. 基于链表的定时器定义
typedef int timer_id;   /**  * The type of callback function to be called by timer scheduler when a timer  * has expired.  *  * @param id                The timer id.  * @param user_data        The user data.  * $param len               The length of user data.  */  typedef int timer_expiry(timer_id id, void *user_data, int len);   /**  * The type of the timer  */  struct timer {         LIST_ENTRY(timer) entries;/**< list entry               */          timer_id id;                /**< timer id                  */          int interval;               /**< timer interval(second) */         int elapse;                 /**< 0 -> interval             */          timer_expiry *cb;          /**< call if expiry            */         void *user_data;           /**< callback arg               */         int len;                        /**< user_data length          */  };
4. 定时器链表
/**  * The timer list  */  struct timer_list {         LIST_HEAD(listheader, timer) header;  /**< list header         */         int num;                                       /**< timer entry number */         int max_num;                               /**< max entry number    */          void (*old_sigfunc)(int);                /**< save previous signal handler */         void (*new_sigfunc)(int);                /**< our signal handler              */          struct itimerval ovalue;                 /**< old timer value */         struct itimerval value;                  /**< our internal timer value */  };
5. 定时器链表的创建和 Destroy
/**  * Create a timer list.  *  * @param count  The maximum number of timer entries to be supported initially.  *  * @return        0 means ok, the other means fail.  */  int init_timer(int count)  {         int ret = 0;          if(count <=0 || count > MAX_TIMER_NUM) {                printf("the timer max number MUST less than %d.\n", MAX_TIMER_NUM);                return -1;         }          memset(&timer_list, 0, sizeof(struct timer_list));         LIST_INIT(&timer_list.header);         timer_list.max_num = count;          /* Register our internal signal handler and store old signal handler */         if ((timer_list.old_sigfunc = signal(SIGALRM, sig_func)) == SIG_ERR) {                 return -1;         }         timer_list.new_sigfunc = sig_func;       /*Setting our interval timer for driver our mutil-timer and store old timer value*/         timer_list.value.it_value.tv_sec = TIMER_START;         timer_list.value.it_value.tv_usec = 0;         timer_list.value.it_interval.tv_sec = TIMER_TICK;         timer_list.value.it_interval.tv_usec = 0;         ret = setitimer(ITIMER_REAL, &timer_list.value, &timer_list.ovalue);          return ret;  }    /**  * Destroy the timer list.  *  * @return          0 means ok, the other means fail.  */  int destroy_timer(void)  {         struct timer *node = NULL;          if ((signal(SIGALRM, timer_list.old_sigfunc)) == SIG_ERR) {                 return -1;         }          if((setitimer(ITIMER_REAL, &timer_list.ovalue, &timer_list.value)) < 0) {                 return -1;         }          while (!LIST_EMPTY(&timer_list.header)) {     /* Delete. */          node = LIST_FIRST(&timer_list.header);                 LIST_REMOVE(node, entries);                 /* Free node */          printf("Remove id %d\n", node->id);                 free(node->user_data);                 free(node);         }          memset(&timer_list, 0, sizeof(struct timer_list));          return 0;  }
6. 向定时器链表中添加定时器
/**  * Add a timer to timer list.  *  * @param interval  The timer interval(second).  * @param cb        When cb!= NULL and timer expiry, call it.  * @param user_data Callback's param.  * @param len       The length of the user_data.  *  * @return          The timer ID, if == INVALID_TIMER_ID, add timer fail.  */  timer_id  add_timer(int interval, timer_expiry *cb, void *user_data, int len)  {         struct timer *node = NULL;          if (cb == NULL || interval <= 0) {                 return INVALID_TIMER_ID;         }       if(timer_list.num < timer_list.max_num) {          timer_list.num++;      } else {          return INVALID_TIMER_ID;      }       if((node = malloc(sizeof(struct timer))) == NULL) {          return INVALID_TIMER_ID;      }      if(user_data != NULL || len != 0) {          node->user_data = malloc(len);          memcpy(node->user_data, user_data, len);          node->len = len;      }       node->cb = cb;      node->interval = interval;      node->elapse = 0;      node->id = timer_list.num;       LIST_INSERT_HEAD(&timer_list.header, node, entries);      return node->id;  }
7. 信号处理函数驱动定时器
/* Tick Bookkeeping */  static void sig_func(int signo)  {         struct timer *node = timer_list.header.lh_first;         for ( ; node != NULL; node = node->entries.le_next) {                 node->elapse++;                 if(node->elapse >= node->interval) {                         node->elapse = 0;                         node->cb(node->id, node->user_data, node->len);                 }         }  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路漫漫其远,吾求索

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值