NGX 信号处理流程
2013-07-11 10:25
162 查看
int ngx_cdecl main(int argc, char *const *argv) { .... #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { // 服务器启动时进行初始化信号处理 return 1; } if (!ngx_inherited && ccf->daemon) { if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } if (ngx_inherited) { ngx_daemonized = 1; } #endif
...... // 单进程服务器 if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); } return 0; }
下来再看看ngx_init_signals函数实现之前先看看结构
typedef struct { int signo; // 信号值 char *signame; // 信号名字 char *name; // 服务器响应信号操作的名字 void (*handler)(int signo);// 信号处理函数 } ngx_signal_t;
再看看全局变量ngx_signal_t signals[] 所有的信号及其处理函数
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", "", SIG_IGN }, { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN }, { 0, NULL, "", NULL } };
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;
//sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号搁置 sigemptyset(&sa.sa_mask); if (sigaction(sig->signo, &sa, NULL) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "sigaction(%s) failed", sig->signame); return NGX_ERROR; } } return NGX_OK; }
下面看看重头函数ngx_signal_handler实现这里解释一个信号处理,其他类似
voidngx_signal_handler(int signo){ char *action; ngx_int_t ignore; ngx_err_t err; ngx_signal_t *sig; ignore = 0; err = ngx_errno;// 检查信号值是否是注册信号 for (sig = signals; sig->signo != 0; sig++) { if (sig->signo == signo) {
// 确认找到 break; } } ngx_time_sigsafe_update(); action = "";// 进程类型 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:// 系统受到 SIGINT,系统调用此信号处理函数,设置全局变量ngx_terminate值置1 下面的分支类似 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: switch (signo) { case ngx_signal_value(NGX_NOACCEPT_SIGNAL): if (!ngx_daemonized) { break; } ngx_debug_quit = 1; 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_REOPEN_SIGNAL): ngx_reopen = 1; action = ", reopening logs"; break; case ngx_signal_value(NGX_RECONFIGURE_SIGNAL): case ngx_signal_value(NGX_CHANGEBIN_SIGNAL): case SIGIO: action = ", ignoring"; break; } break; } ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, "signal %d (%s) received%s", signo, sig->signame, action); if (ignore) { ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0, "the changing binary signal is ignored: " "you should shutdown or terminate " "before either old or new binary's process"); } if (signo == SIGCHLD) { ngx_process_get_status(); } ngx_set_errno(err);}
这里处理完毕了吗,还没有以服务器模式为NGX_PROCESS_MASTER为例,ngx_master_process_cycle函数中
创建完工作进程和管理进程后,主进程进入循环,并停滞在
// 等待信号唤醒 sigsuspend(&set);// 注意set是一个空信号集
进程收到信号并处理信号函数后,此函数返回,
程序进入下面执行ngx_terminate在信号处理函数中被置1
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_TERMINATE_SIGNAL信号 ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; }
这就是信号处理流程,那么有一个问题,信号如何被发送的?
相关文章推荐
- 语音信号处理概述及流程
- DL4J源码阅读(六):LSTM信号前传处理流程
- 白话/图示 信号处理流程
- linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)
- Android--音频开发--信号从麦克风到扬声器的处理流程
- linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)
- linux 信号处理流程
- linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)
- Android Init进程对信号的处理流程详细介绍
- linux系统下进程的信号(signal)处理流程是怎么样的?
- linux信号处理流程前篇---内核态与用户态的切换
- linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)
- linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)
- 浅析frmware的加载和init通过netlink处理uevent事件的一般流程(转)
- 巧用QSignalMapper分类有序地处理大量信号
- nginx upstream模块详解(处理流程篇二 upstream与event_pipe交互)
- Linux 信号signal处理机制
- Linux 多线程应用中如何编写安全的信号处理函数
- 从点击屏幕到事件处理的事件分发源码流程
- 数图处理主流程