nginx模块开发(31)—定时器模型

http://cjhust.blog.163.com/blog/static/175827157201348112639361/

 

Hello world

模块功能:注册一个定时事件,每过一秒钟打印一次hello world。ngx_add_timer函数就是用来完成将一个新的定时事件加入定时器红黑树中,定时事件被执行后,就会从树中移除,因此要想不断的循环打印hello world,就需要在事件回调函数被调用后再将事件给添加到定时器红黑树中。 ngx_http_hello_process_init是注册在模块的进程初始化阶段的回调函数上。

static ngx_connection_t dummy;  

static ngx_event_t ev;   

 

 

static void  

ngx_http_hello_print(ngx_event_t *ev)   

{  

    printf("hello world\n");  

  

    ngx_add_timer(ev, 1000);  

}  

  

  

static ngx_int_t  

ngx_http_hello_process_init(ngx_cycle_t *cycle)  

{  

    dummy.fd = (ngx_socket_t) -1;   

  

    ngx_memzero(&ev, sizeof(ngx_event_t));  

  

    ev.handler = ngx_http_hello_print;  

    ev.log = cycle->log;  

    ev.data = &dummy;  

  

    ngx_add_timer(&ev, 1000);  

  

    return NGX_OK;  

}

 

4、操作函数

ngx_event_timer_init

函数功能:完成定时器红黑树的建树操作。

clip_image001

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_event_timer_mutex->log = log;

        return NGX_OK;

    }

 

    ngx_event_timer_mutex = ngx_mutex_init(log, 0);

    if (ngx_event_timer_mutex == NULL) {

        return NGX_ERROR;

    }

 

#endif

 

    return NGX_OK;

}

 

clip_image001[4]

ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)

 //timer就是一个int的值,表示超时的事件,用于表示红黑树节点的key

static ngx_inline void

ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)

{

    ngx_msec_t      key;

    ngx_msec_int_t  diff;

 

    key = ngx_current_msec + timer;   //现在时间+超时时间=过期时间

    //已经设置了定时器

    if (ev->timer_set) {

 

        /*

         * Use a previous timer value if difference between it and a new

         * value is less than NGX_TIMER_LAZY_DELAY milliseconds: this allows

         * to minimize the rbtree operations for fast connections.

         */

 

        diff = (ngx_msec_int_t) (key - ev->timer.key);

        //2次比较相近,则忽略这次的

        if (ngx_abs(diff) < NGX_TIMER_LAZY_DELAY) {  //300

            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,

                           "event timer: %d, old: %M, new: %M",

                            ngx_event_ident(ev->data), ev->timer.key, key);

            return;

        }

        //否则,删除old

        ngx_del_timer(ev);

    }

 

    ev->timer.key = key;

 

    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,

                   "event timer add: %d: %M:%M",

                    ngx_event_ident(ev->data), timer, ev->timer.key);

 

    ngx_mutex_lock(ngx_event_timer_mutex);

    //事件的timer域插入到红黑树当中  

    ngx_rbtree_insert(&ngx_event_timer_rbtree, &ev->timer);   // ev->timer是node

 

    ngx_mutex_unlock(ngx_event_timer_mutex);

 

    ev->timer_set = 1;

}

ngx_event_del_timer(ngx_event_t *ev)

static ngx_inline void

ngx_event_del_timer(ngx_event_t *ev)

{

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,

                   "event timer del: %d: %M",

                    ngx_event_ident(ev->data), ev->timer.key);

 

    ngx_mutex_lock(ngx_event_timer_mutex);

 

    ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);

 

    ngx_mutex_unlock(ngx_event_timer_mutex);

 

#if (NGX_DEBUG)

    ev->timer.left = NULL;

    ev->timer.right = NULL;

    ev->timer.parent = NULL;

#endif

 

    ev->timer_set = 0;

}

ngx_event_find_timer(void)

函数功能:用于获取当前事件红黑树中最小的超时时间,将其提供给epoll,让epoll的wait在这个时间内唤醒。

ngx_msec_t

ngx_event_find_timer(void)

{

    ngx_msec_int_t      timer;

    ngx_rbtree_node_t  *node, *root, *sentinel;

 

    if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {

        return NGX_TIMER_INFINITE;

    }

 

    ngx_mutex_lock(ngx_event_timer_mutex);

 

    root = ngx_event_timer_rbtree.root;

    sentinel = ngx_event_timer_rbtree.sentinel;

    node = ngx_rbtree_min(root, sentinel);

 

    ngx_mutex_unlock(ngx_event_timer_mutex);

 

    timer = (ngx_msec_int_t) (node->key - ngx_current_msec);

 

    return (ngx_msec_t) (timer > 0 ? timer : 0);

}

ngx_event_expire_timers(void)

函数功能:处理红黑树中的所有超时事件。

void

ngx_event_expire_timers(void)

{

    ngx_event_t        *ev;

    ngx_rbtree_node_t  *node, *root, *sentinel;

 

    sentinel = ngx_event_timer_rbtree.sentinel;

   

    //找到所有的超时的timer,然后处理它们

    for ( ;; ) {

 

        ngx_mutex_lock(ngx_event_timer_mutex);

 

        root = ngx_event_timer_rbtree.root;

 

        if (root == sentinel) {

            return;

        }

        //获取key最小的节点  

        node = ngx_rbtree_min(root, sentinel);

    

        //该节点是否超时

        if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) { 

            ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));

 

            //类似于ngx_event_del_timer

            ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);

 

            ngx_mutex_unlock(ngx_event_timer_mutex);

            ev->timer_set = 0;         

            ev->timedout = 1;

            ev->handler(ev);

 

            continue;

        }

 

        break;

    }

 

    ngx_mutex_unlock(ngx_event_timer_mutex);

}

5、一个例子

ngx_process_events_and_timers(ngx_cycle_t *cycle)

void

ngx_process_events_and_timers(ngx_cycle_t *cycle)

{

    ngx_uint_t  flags;

    ngx_msec_t  timer, delta;

 

    if (ngx_timer_resolution) {  //0

        timer = NGX_TIMER_INFINITE;

        flags = 0;

 

    } else {

        timer = ngx_event_find_timer();                        //返回的是最小的超时时间,单位是毫秒

        flags = NGX_UPDATE_TIME;// 1

 

#if (NGX_THREADS)

 

        if (timer == NGX_TIMER_INFINITE || timer > 500) {

            timer = 500;

        }

 

#endif

    }

 

    。。。

 

    delta = ngx_current_msec;

 

   //下面这个函数就是处理事件的函数(包括新连接建立事件),网络IO事件等等

    (void) ngx_process_events(cycle, timer, flags);    //ngx_epoll_process_events   

 

    delta = ngx_current_msec - delta;                       //时间差,因为ngx_time_update已更新

 

    。。。

 

    if (delta) {

        ngx_event_expire_timers();                           //处理所有的超时事件

    }

 

    。。。

}

 

 

转载于:https://www.cnblogs.com/dream397/p/4098093.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值