在前面的文章里面就说到了在事件循环中除了要处理所有的从epoll中获取的事件之外,还要处理一些timer事件,这篇文章就讲讲Nginx的timer是如何实现的。
在讲Nginx的实现之前,我们可以先回顾一下linux的定时器的实现。在linux中通过每次系统定时器时钟的中断的中断处理程序来设置相应的软中断位,该软中断的中断处理程序目的就是为了扫描系统中所有挂起的定时器,如果他们已经超时的话,那么就调用他们相应的函数,这样说白了就是利用中断来实现定时器。
而在Nginx中,timer是自己实现的,而且实现的方法完全不同,而是通过红黑树来维护所有的timer节点,在worker进程的每一次循环中都会调用ngx_process_events_and_timers函数,在该函数中就会调用处理定时器的函数ngx_event_expire_timers,每次该函数都不断的从红黑树中取出时间值最小的,查看他们是否已经超时,然后执行他们的函数,直到取出的节点的时间没有超时为止。其实在Nginx的运行环境中,这种实现方式可能比linux本身的实现方式更为高效。
首先我们来看Nginx的定时器的初始化,在ngx_event_process_init函数中( Ngx_event.c):
/*初始化计时器,此处将会创建起一颗红黑色,来维护计时器。*/
if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
return NGX_ERROR;
}
嗯,就是这个函数,那么接下来我们来看这个函数吧,
//timer的初始化
ngx_int_t
ngx_event_timer_init(ngx_log_t *log)
{
//初始化红黑树
ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
ngx_rbtree_insert_timer_value);
#if (NGX_THREADS)
if (ngx_event_timer_mutex) {
ngx_even