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返回,然后又开始保存调用时
的堵塞状态。这样保持临界区不被信号干扰。