nginx 通过Signal发送控制信号

nginx 通过Signal发送控制信号,类似 nginx -s reload 的流程如下:

1 信号结构体

// 信号结构体
typedef struct {
    int     signo;      //信号编号
    char   *signame;    //信号表现形式,如“SIGIO”
    char   *name;       //信号名称,如“stop,reload”
    void  (*handler)(int signo, siginfo_t *siginfo, void *ucontext); //信号处理函数
} ngx_signal_t;

2 在nginx的main()函数里调用ngx_get_options()

int ngx_cdecl
main(int argc, char *const *argv)
{
    ...
    // 获取命令行参数,比如-v -V,根据不同的参数,初始化对应的变量
    /*
        case 'h':
            ngx_show_version = 1;
            ngx_show_help = 1;
            break;

        case 'v':
            ngx_show_version = 1;
            break;

        case 'V':
            ngx_show_version = 1;
            ngx_show_configure = 1;
            break;

        case 't':
            ngx_test_config = 1;
            break;

        case 'T':
            ngx_test_config = 1;
            ngx_dump_config = 1;
            break;

        case 'q':
            ngx_quiet_mode = 1;
            break;
     */
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }
    ...
}

3 ngx_get_options()函数解析命令行参数

static ngx_int_t
ngx_get_options(int argc, char *const *argv)
{
    		...
            // nginx -s reload、stop,quit、open等相关命令解析
            case 's':
                if (*p) {
                    ngx_signal = (char *) p;

                } else if (argv[++i]) {
                    ngx_signal = argv[i];

                } else {
                    ngx_log_stderr(0, "option \"-s\" requires parameter");
                    return NGX_ERROR;
                }

                if (ngx_strcmp(ngx_signal, "stop") == 0
                    || ngx_strcmp(ngx_signal, "quit") == 0
                    || ngx_strcmp(ngx_signal, "reopen") == 0
                    || ngx_strcmp(ngx_signal, "reload") == 0)
                {
                    ngx_process = NGX_PROCESS_SIGNALLER;
                    goto next;
                }

                ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
                return NGX_ERROR;

            default:
                ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
                return NGX_ERROR;
            }
        }
        ...
    return NGX_OK;
}

在nginx main函数调用ngx_get_options()函数解析,然后调用ngx_signal_process()函数

4 ngx_signal_process()函数

① 打开工作进程文件,读取pid
② 调用ngx_os_signal_process函数处理

ngx_int_t
ngx_signal_process(ngx_cycle_t *cycle, char *sig)
{
    ssize_t           n;
    ngx_pid_t         pid;
    ngx_file_t        file;
    ngx_core_conf_t  *ccf;
    u_char            buf[NGX_INT64_LEN + 2];

    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started");

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    ngx_memzero(&file, sizeof(ngx_file_t));

    file.name = ccf->pid;
    file.log = cycle->log;

    file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
                            NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS);

    if (file.fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", file.name.data);
        return 1;
    }

    n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0);

    if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", file.name.data);
    }

    if (n == NGX_ERROR) {
        return 1;
    }

    while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ }

    pid = ngx_atoi(buf, ++n);

    if (pid == (ngx_pid_t) NGX_ERROR) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
                      "invalid PID number \"%*s\" in \"%s\"",
                      n, buf, file.name.data);
        return 1;
    }

    return ngx_os_signal_process(cycle, sig, pid);
}

5 ngx_os_signal_process()函数
遍历signals数组,根据给定信号name,找到对应signo,调用kill命令,向该pid发送signo号信号

ngx_int_t
ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_pid_t pid)
{
    ngx_signal_t  *sig;

    for (sig = signals; sig->signo != 0; sig++) {
        if (ngx_strcmp(name, sig->name) == 0) {
            if (kill(pid, sig->signo) != -1) {
                return 0;
            }

            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "kill(%P, %d) failed", pid, sig->signo);
        }
    }

    return 1;
}

个人nginx源码注释项目,感兴趣的可以围观一下,欢迎一起学习!
github地址:git@github.com:HelloMrShu/nginx_comment_1.17.x.git

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值