nginx源码分析—信号初始化和使用
2017-04-19 16:44
381 查看
序
ngx_init_signals()函数
ngx_signal_t结构
signals数组
sigaction结构
ngx_signal_handler()函数
ngx_master_process_cycle()数
小结
当收到信号会先调用handler函数。
sigsuspend()//等待信号,知道有信号才苏醒,在ngx_signal_handler响应处理之后
ngx_init_signals()函数
ngx_signal_t结构
signals数组
sigaction结构
ngx_signal_handler()函数
ngx_master_process_cycle()数
小结
1序
本文主要分析nginx信号初始化及其处理,信号处理用于master进程的接收reload,stop等操作。2.1 ngx_init_signals()函数
ngx_int_t ngx_init_signals(ngx_log_t *log) { ngx_signal_t *sig; struct sigaction sa; for (sig = signals; sig->signo != 0; sig++) { ngx_memzero(&sa, sizeof(struct sigaction)); sa.sa_handler = sig->handler; sigemptyset(&sa.sa_mask);//清空此信号集 if (sigaction(sig->signo, &sa, NULL) == -1) {//设置相关singl的action //signaction,则可以设置比较多的消息。尤其是在信号处理函数过程中接受信号,进行何种处理 //替代signal 来设计的较稳定的信号处理 #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; }
2.2 ngx_signal_t结构
//Nginx服务器的启动、停止和升级都是通过信号控制的 typedef struct { int signo;//信号的编号 char *signame;//信号的字符串表现形式,如"SIGIO"。 char *name;//信号的名称,如"stop"。 void (*handler)(int signo);//信号处理函数。 } ngx_signal_t;
当收到信号会先调用handler函数。
2.3 signals数组
ngx_signal_t signals[] = { { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),//RECONFIGURE信号,重新读取配置信息 "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),//SIGHUP信号 "reload", ngx_signal_handler }, { ngx_signal_value(NGX_REOPEN_SIGNAL), "SIG" ngx_value(NGX_REOPEN_SIGNAL),//SIGHUP信号 "reopen", ngx_signal_handler }, { ngx_signal_value(NGX_NOACCEPT_SIGNAL),//NOACCEPT信号,工作进程不接受事件 "SIG" ngx_value(NGX_NOACCEPT_SIGNAL), "", ngx_signal_handler }, { ngx_signal_value(NGX_TERMINATE_SIGNAL),//TERMINATE信号,工作进程终止 "SIG" ngx_value(NGX_TERMINATE_SIGNAL), "stop", ngx_signal_handler }, { ngx_signal_value(NGX_SHUTDOWN_SIGNAL), "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),//SHUTDOWN信号,结束网络通信 "quit", ngx_signal_handler }, { ngx_signal_value(NGX_CHANGEBIN_SIGNAL),//CHANGEBIN信号,热升级Nginx运行程序 "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL), "", ngx_signal_handler }, //以下是常见的系统信号 { SIGALRM, "SIGALRM", "", ngx_signal_handler }, { SIGINT, "SIGINT", "", ngx_signal_handler },//来自键盘的中断信号 ( ctrl + c ) { SIGIO, "SIGIO", "", ngx_signal_handler },//表示 Io 有数据可供读取 { SIGCHLD, "SIGCHLD", "", ngx_signal_handler },//标识子进程停止或结束的信号 { SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN }, //在linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。 //这个信号的缺省处理方法是退出进程 { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN },//无效系统调用 { 0, NULL, "", NULL } };
3. ngx_signal_handler()函数
主要是赋值ngx_quit 、ngx_terminate 、ngx_noaccept 等变量在ngx_master_process_cycle()中做判断switch (ngx_process) { case NGX_PROCESS_MASTER: case NGX_PROCESS_SINGLE: switch (signo) { case ngx_signal_value(NGX_SHUTDOWN_SIGNAL): ngx_quit = 1; action = ", shutting down"; break; case ngx_signal_value(NGX_TERMINATE_SIGNAL): case SIGINT: ngx_terminate = 1; action = ", exiting"; break; case ngx_signal_value(NGX_NOACCEPT_SIGNAL): if (ngx_daemonized) { ngx_noaccept = 1; action = ", stop accepting connections"; } break; case ngx_signal_value(NGX_RECONFIGURE_SIGNAL): ngx_reconfigure = 1; action = ", reconfiguring"; break; case ngx_signal_value(NGX_REOPEN_SIGNAL): ngx_reopen = 1; action = ", reopening logs"; break; case ngx_signal_value(NGX_CHANGEBIN_SIGNAL): if (getppid() > 1 || ngx_new_binary > 0) { /* * Ignore the signal in the new binary if its parent is * not the init process, i.e. the old binary's process * is still running. Or ignore the signal in the old binary's * process if the new binary's process is already running. */ action = ", ignoring"; ignore = 1; break; } ngx_change_binary = 1; action = ", changing binary"; break; case SIGALRM: ngx_sigalrm = 1; break; case SIGIO: ngx_sigio = 1; break; case SIGCHLD: ngx_reap = 1; break; } break; case NGX_PROCESS_WORKER: case NGX_PROCESS_HELPER:
4. ngx_master_process_cycle()数
sigprocmask(SIG_BLOCK, &set, NULL) //将SIGINT信号阻塞sigsuspend()//等待信号,知道有信号才苏醒,在ngx_signal_handler响应处理之后
void 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; sigemptyset(&set); 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(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)); //将SIGINT信号阻塞,同时保存当前信号集 //记住是屏蔽,不是消除,就是来了信号,如果当前是block,则先不传递给当前进程,但是一旦unblock,则信号会重新到达 if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); ........ ........ for ( ;; ) { sigsuspend(&set); //用于在接收到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止 ngx_time_update(); if (ngx_terminate) { if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; if (delay > 1000) { ngx_signal_worker_processes(cycle, SIGKILL); } else { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } if (ngx_quit) { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; }
5. 小结
再接再厉
相关文章推荐
- nginx源码分析—信号初始化
- Nginx源码分析-事件驱动的初始化
- nginx源码分析—全局变量ngx_cycle的初始化
- nginx源码分析——初始化log
- nginx源码分析之网络初始化
- nginx源码分析--event事件驱动初始化
- nginx源码分析—模块及其初始化
- nginx源码分析(2)——http模块的初始化过程
- nginx源码分析(2)——http模块的初始化过程
- Nginx源码分析-事件驱动的初始化
- nginx源码分析--nginx外部信号 命令参数
- Nginx源码分析---Nginx启动初始化过程(一)
- Nginx源码分析-启动初始化过程(二)
- nginx源码分析—模块及其初始化
- nginx源码分析—模块及其初始化 .
- Nginx源码分析-启动初始化过程(一)
- Nginx源码分析---Nginx启动初始化过程(二)
- Nginx源码分析-启动初始化过程(一)
- nginx源码分析--nginx上下文结构初始化
- libevent2源码分析之三:信号的初始化流程