nginx源码分析 (信号机制)

这篇文章讲解nginx的信号机制,因为是信号,所以其他方面的没有深究,放在后面分享出来,欢迎有兴趣的朋友留言交流

nginx运行的进程模式为master-worker的话,那master和worker进程间是通过信号来通信,关于信号相关的知识可以参考下面的链接Linux信号(signal) 机制分析

下面讲解代码执行流程都是以quit命令来执行的

一、信号的安装

nginx启动的过程中,master进程会安装自定义的信号处理机制,定义了哪些信号需要自己安装处理函数,nginx.c中的main函数中,有个ngx_init_signals函数就是用来安装自定义信号的,安装之后,后面fork出来的worker进程也会继承安装的自定义信号处理机制,因为fork出来的worker进程会复制一份和父进程一模一样的地址空间,包括所有资源,我们看下代码

ngx_int_t
ngx_init_signals(ngx_log_t *log)
{
    ngx_signal_t      *sig;
    struct sigaction   sa;
    //signals已经是初始化过的全局变量,存储的就是各个信号的回调函数相关信息
    for (sig = signals; sig->signo != 0; sig++) {
        ngx_memzero(&sa, sizeof(struct sigaction));

        if (sig->handler) {
            sa.sa_sigaction = sig->handler;
            sa.sa_flags = SA_SIGINFO;

        } else {
            sa.sa_handler = SIG_IGN;
        }

        sigemptyset(&sa.sa_mask);
        if (sigaction(sig->signo, &sa, NULL) == -1) {
#if (NGX_VALGRIND)
            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                          "sigaction(%s) failed, ignored", sig->signame);
#else
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                          "sigaction(%s) failed", sig->signame);
            return NGX_ERROR;
#endif
        }
    }

    return NGX_OK;
}

接下来我们在看下signals这个全局变量的内容,这些信号就是对应nginx命令行的一些处理,例如nginx -s stop|quit|reload....

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),
      "",
      ngx_signal_handler },

    { SIGALRM, "SIGALRM", "", ngx_signal_handler },

    { SIGINT, "SIGINT", "", ngx_signal_handler },

    { SIGIO, "SIGIO", "", ngx_signal_handler },

    { SIGCHLD, "SIGCHLD", "", ngx_signal_handler },

    { SIGSYS, "SIGSYS, SIG_IGN", "", NULL },

    { SIGPIPE, "SIGPIPE, SIG_IGN", "", NULL },

    { 0, NULL, "", NULL }
};

安装完nginx要处理的信号之后,因为我们这篇讲的是nginx信号的机制,所以我们直接看ngx_master_process_cycle 

二、 master进程阻塞等待信号

1、首先初始化一个信号集并且置空,sigemptyset(&set);

2、然后将需要处理的信号添加到信号集中,sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));

3、先暂时用sigprocmask(SIG_BLOCK, &set, NULL),将上面的信号集阻塞,此刻如果有信号产生,内核不会把信号传递给进程,就是所谓的阻塞

4、然后信号集再置为空,sigemptyset(&set);

5、在master无限循环中,用sigsuspend(&set);,将之前阻塞的信号从掩码信号集中删除,然后挂起等待信号

就这样master进程就会阻塞在sigsuspend的调用中,直到有信号产生。

接下来我们看下如果有信号产生,接下来会怎么执行

当有信号产生的时候,nginx会捕获信号然后调用定义的信号处理函数(就是之前安装的信号处理器),信号处理函数主要是设置一些信号标识,然后sigsuspend调用返回,然后继续执行下面的代码,可以看源码中下面的
if (ngx_terminate)  if (ngx_quit)  一些信号标识的判断,就是根据信号处理函数处理的信号标识进行不同的操作。

ngx_master_process_cycle(ngx_cycle_t *cycle)
{
    char              *title;
    u_char            *p;
    size_t             size;
    ngx_int_t          i;
    ngx_uint_t         n, sigio;
    sigset_t           set;
    struct itimerval   itv;
    ngx_uint_t         live;
    ngx_msec_t         delay;
    ngx_listening_t   *ls;
    ngx_core_conf_t   *ccf;
    //将参数set信号集初始化并清空
    sigemptyset(&set);
    //将参数signum 代表的信号加入至参数set 信号集里
    //SIGCHLD子进程退出发出的信号
    sigaddset(&set, SIGCHLD);
    sigaddset(&set, SIGALRM);
    sigaddset(&set, SIGIO);
    sigaddset(&set, SIGINT);
    sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
    sigaddset(&set, ngx_signal_value(NG
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值