前言
接着上篇的启动流程,先从创建worker子进程,然后worker进程的循环执行,之后再master进程的执行,直接源码分析,看一点是一点。
创建worker子进程
OK,从这里开始。。。
static void
ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{
ngx_int_t i;
ngx_channel_t ch;
// NGX_LOG_NOTICE级别的error日志
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
ngx_memzero(&ch, sizeof(ngx_channel_t));
// 这个是在创建一个worker进程后,用来通知给其他已有worker进程的命令
ch.command = NGX_CMD_OPEN_CHANNEL;
// 创建n个worker进程,n来自配置文件中的数目
for (i = 0; i < n; i++) {
// 创建worker进程函数,下面详述
ngx_spawn_process(cycle, ngx_worker_process_cycle,
(void *) (intptr_t) i, "worker process", type);
// 记录上面创建的新worker进程的进程号,全局进程数组中的下标以及其父进程socket fd,之后用于向其他已有进程广播
// ngx_process_slot为全局变量,在ngx_spawn_process()中被赋值,
// 意为新创建worker进程在全部进程数组ngx_processes[]中的下标
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
// 这里每个子进程和父进程之间使用的是socketpair系统调用建立起来的全双工的socket
// channel[]在父子进程中各有一套,channel[0]为写端,channel[1]为读端
ch.fd = ngx_processes[ngx_process_slot].channel[0];
// 给每一个已有进程的父进程发送刚创建worker进程的信息,下面详述
ngx_pass_open_channel(cycle, &ch);
}
}
在源码中,nginx_process.h中,有以下几种属性标识:
- NGX_PROCESS_NORESPAWN :子进程退出时,父进程不会再次重启
- NGX_PROCESS_JUST_SPAWN :--
- NGX_PROCESS_RESPAWN :子进程异常退出时,父进程需要重启
- NGX_PROCESS_JUST_RESPAWN :--
- NGX_PROCESS_DETACHED :热代码替换,暂时估计是用于在不重启Nginx的情况下进行软件升级
这个是关于Nginx配置重载的内容。当Master进程检测到需要进程重载时,会进行ngx_init_cycle(),然后启动新的worker进程。