Linux 下定时器的实现方式分析(2)

基于链表实现的定时器可以定义为:

清单 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          */
};

定时器的时间间隔以 interval 表示,而 elapse 则在 PerTickBookkeeping() 时递增,直到 interval 表示定时器中止,此时调用回调函数 cb 来执行相关的行为,而 user_data 和 len 为用户可以传递给回调函数的参数。

所有的定时器实例以链表来管理:

清单 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 */
};

这里关于链表的实现使用了 BSD 风格关于链表的一组宏,避免了再造轮子;该结构中,old_sigfunc 在 init_timer 初始定时器链表时候用来保存系统对 SIGALRM 的处理函数,在定时器系统 destory 时用来恢复到之前的处理函数; ovalue 的用途与此类似。

清单 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;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwpfxs.html