NGINX多线程信号的使用

3390阅读 0评论2012-06-27 jueduiyingxiong
分类:LINUX

  sigset_t           set;
    struct itimerval   itv;
    ngx_uint_t         live;
    ngx_msec_t         delay;
    ngx_listening_t   *ls;
    ngx_core_conf_t   *ccf;

    sigemptyset(&set); //sigemptyset()用来将参数set信号集初始化并清空。
    sigaddset(&set, SIGCHLD); //sigaddset()用来将参数signum 代表的信号加入至参数set 信号集里。
    sigaddset(&set, SIGALRM);
    sigaddset(&set, SIGIO); //把异步io信号屏蔽,下面用到异步id
    sigaddset(&set, SIGINT);
    sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));

    if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { //SIG_BLOCK    该进程新的信号屏蔽字是其当前信号屏蔽字和set指向信号集的并集。set包含了我们希望阻塞的附加信号。
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "sigprocmask() failed");
    }

    //下面所关键代码区,不受相应信号干扰
    sigemptyset(&set); //清空屏蔽字


    size = sizeof(master_process);

    //所有输入参数的长度
    for (i = 0; i < ngx_argc; i++) {
        size += ngx_strlen(ngx_argv[i]) + 1;
    }

    title = ngx_pnalloc(cycle->pool, size);

    p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); //title = master process
    for (i = 0; i < ngx_argc; i++) { //组合P的值
        *p++ = ' ';
        p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
    }

    //linux调用
    ngx_setproctitle(title); //master process /root/nginx/nginx-1.0.12/objs/nginx -c /usr/local/nginx/conf/nginx.conf


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

    ngx_start_worker_processes(cycle, ccf->worker_processes,
                               NGX_PROCESS_RESPAWN); //启动八个worker进程
    ngx_start_cache_manager_processes(cycle, 0); //启动cache进程,管理

    ngx_new_binary = 0;
    delay = 0;
    sigio = 0;
    live = 1;

    for ( ;; ) {
        if (delay) { //判断是否延时,如果延时那么设置
            if (ngx_sigalrm) { //是否有信号设置
                sigio = 0;
                delay *= 2;
                ngx_sigalrm = 0;
            }

            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                           "termination cycle: %d", delay);

            //设置定时
            itv.it_interval.tv_sec = 0;
            itv.it_interval.tv_usec = 0;
            itv.it_value.tv_sec = delay / 1000;
            itv.it_value.tv_usec = (delay % 1000 ) * 1000;

            if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { //设置定时器,如果线程挂起事件到达,那么唤醒
                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                              "setitimer() failed");
            }
        }

        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");

        sigsuspend(&set);//挂起信号集,为空,表明不阻塞任何信号。等到有信号发生才走下去。

        ngx_time_update();


总结:多线程要保护代码区域,首先先调用sigprocmask把需要的信号都堵塞主,然后调用sigsuspend访问,
把需要堵塞的信号堵塞,这里不堵塞任何信号。然后信号到来的时候,sigsuspend返回,然后又开始保存调用时
的堵塞状态。这样保持临界区不被信号干扰。
上一篇:Nginx汇编锁完全可以替代临界互斥锁,成为最优秀的多线程锁
下一篇:NGINX一些语法基础的学习