注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

云水居

云在青山水在天,人在江湖不得闲

 
 
 

日志

 
 

nginx的信号处理  

2010-10-18 21:33:01|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

查看全文


nginx 支持热重启,热升级。即在不停止服务的情况下完成系统的升级与运行参数修改。这些都是建立在信号机制的基础上的。
如果要在中断现有HTTP服务的情况下重启 nginx,执行如下命令即可。
kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
如果修改了 nginx 的源代码,并重新构建并测试过了,也可以在不中断现有HTTP的服务下热升级 nginx,命令如下:
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
这时nginx的新旧版本同时工作,如果要让旧版本程序服务完正在连接的HTTP请求后即退出,命令如下:
kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin`
过一段时间后,旧进程的worker 进程全部退出了,就可以关闭旧进程的master进程了
kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
这里升级完成。

这些都是机制的实现代码主要在os/unix/ngx_process.c 和 os/unix/ngx_process_cycle.c 中。
操作机制
根据 nginx 的运行机制,主进程在完成配置文件解析,启动工作进程等主要任务后,就会进入一个主循环
os/unix/ngx_process_cycle.c 的 ngx_master_process_cycle 函数的框架如下
ngx_master_process_cycle(ngx_cycle_t *cycle)
{
    //...
    for ( ;; ) { //循环
        //...
        sigsuspend(&set);
        ngx_time_update(0, 0);//update timer
        if (ngx_reap) { //clear, if clean ok, set live=0, and ready to exit
            live = ngx_reap_children(cycle);
        }
        if (!live && (ngx_terminate || ngx_quit)) {
            ngx_master_process_exit(cycle);
        }
        if (ngx_terminate) {
                ngx_signal_worker_processes(cycle, SIGKILL);
        }
        if (ngx_quit) {//close process, close sockets
            ngx_signal_worker_processes(cycle,
                                        ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
        }
        if (ngx_reconfigure) {//reconfigure
             //...
        }
        if (ngx_restart) {
            //...
        }
        if (ngx_reopen) {
            //...
        }
        if (ngx_change_binary) {
//...
这样看来结构很清晰,首先调用sigsuspend等待信号,然后等信号触发后,判断几个全局变量(ngx_restart/ngx_reopen/...)来决定要执行什么操作,基于这样的思路,nginx 的信号处理函数也基本可以猜到了,就是根据信号的种类,修改相应的全局变量。现在开始追踪信号处理函数的设置代码。
信号设置
从头开始跟踪代码,查找设置signal的地方,在 core/nginx.c 文件的 main 函数中,有一个函数调用的地方
int ngx_cdecl main(int argc, char * const *argv){
    //...
    if (ngx_init_signals(cycle->log) != NGX_OK) { //init signals
        return 1;
    }
}
跟踪 ngx_init_signals 函数,进入os/unix/ngx_process.c 文件。代码如下所示:
ngx_int_t ngx_init_signals(ngx_log_t *log)
{  
    ngx_signal_t      *sig;
    struct sigaction   sa;
    for (sig = signals; sig->signo != 0; sig++) {// 遍历signals数组
        ngx_memzero(&sa, sizeof(struct sigaction));
        sa.sa_handler = sig->handler;
        sigemptyset(&sa.sa_mask);//no block
        if (sigaction(sig->signo, &sa, NULL) == -1) { //调用sigaction,设置信号的处理函数: signno<->handler
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                          "sigaction(%s) failed", sig->signame);
            return NGX_ERROR;
        }
    }
    return NGX_OK;
}
代码很简单,基本不用解释,信号和信号处理函数全在signals这个变量里,这个变量也在 os/unix/ngx_process.c文件中,代码如下:
ngx_signal_t  signals[] = {
    { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
      "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
      "reload",
      ngx_signal_handler },  
    { ngx_signal_value(NGX_REOPEN_SIGNAL),
      "SIG" ngx_value(NGX_REOPEN_SIGNAL),
      "reopen",
      ngx_signal_handler },  
    { ngx_signal_value(NGX_NOACCEPT_SIGNAL),
      "SIG" ngx_value(NGX_NOACCEPT_SIGNAL),
      "",
      ngx_signal_handler },  
    { ngx_signal_value(NGX_TERMINATE_SIGNAL),
      "SIG" ngx_value(NGX_TERMINATE_SIGNAL),
      "stop",
      ngx_signal_handler },  
    { ngx_signal_value(NGX_SHUTDOWN_SIGNAL),
      "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),
      "quit",
      ngx_signal_handler },  
    { ngx_signal_value(NGX_CHANGEBIN_SIGNAL),
      "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),
   &n

查看全文

  评论这张
 
阅读(2397)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017