linux事件池触发定时器,Nginx定时器的实现及定时事件的使用

Nginx提供一套高效的定时器实现,除了Nginx核心能够使用定时器以外,我们在进行模块开发的时候也可以使用定时器来完成一些定时执行的任务。Nginx定时器实现的核心是使用一棵红黑树来存储各个定时事件,每次循环的时候就从这棵树里找出超时的事件,然后一一触发,完成定时任务操作。下面简单的描述一下Nginx在实现定时器时的几个关键点。本文是基于Linux的epoll来描述的定时器实现。

定时器初始化

Nginx阻塞于epoll_wait时可能被3类事件唤醒,分别是有读写事件发生、等待时间超时和信号中断。等待超时和信号中断都是与定时器实现相关的,它们的初始化发生在ngx_event_core_module模块的进程初始化阶段,代码段如下:

if(ngx_event_timer_init(cycle->log) == NGX_ERROR) {

returnNGX_ERROR;

}

调用ngx_event_timer_init函数完成定时器红黑树的建树操作,这棵红黑树在存储定时器的同时,也为epoll_wait提供了等待时间。

if(ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {

structsigaction  sa;

structitimerval  itv;

ngx_memzero(&sa,sizeof(structsigaction));

sa.sa_handler = ngx_timer_signal_handler;

sigemptyset(&sa.sa_mask);

if(sigaction(SIGALRM, &sa, NULL) == -1) {

ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,

"sigaction(SIGALRM) failed");

returnNGX_ERROR;

}

itv.it_interval.tv_sec = ngx_timer_resolution / 1000;

itv.it_interval.tv_usec = (ngx_timer_resolution % 1000) * 1000;

itv.it_value.tv_sec = ngx_timer_resolution / 1000;

itv.it_value.tv_usec = (ngx_timer_resolution % 1000 ) * 1000;

if(setitimer(ITIMER_REAL, &itv, NULL) == -1) {

ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,

"setitimer() failed");

}

}

使用setitimer系统调用设置系统定时器,每当到达时间点后将发生SIGALRM信号,同时epoll_wait的阻塞将被信号中断从而被唤醒执行定时事件。其实,这段初始化并不是一定会被执行的,它的条件ngx_timer_resolution就是通过配置指令timer_resolution来设置的,如果没有配置此指令,就不会执行这段初始化代码了。也就是说,配置文件中使用了timer_resolution指令后,epoll_wait将使用信号中断的机制来驱动定时器,否则将使用定时器红黑树的最小时间作为epoll_wait超时时间来驱动定时器。0b1331709591d260c1c78e86d0c51c18.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值