一般情况下nginx都是采用worker与master的方式启动的,这里我们将分析master进程,我们知道在nginx的main函数的最后会调用ngx_master_process_cycle函数,开始启动worker-master模式,那么我们就从这个函数开始,该函数的定义在src/os/unix/Ngx_process_cycle.c当中:
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));
//将上面的信号集中的信号全部屏蔽
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"sigprocmask() failed");
}
首先就是直接屏蔽掉一些信号。接下来就是一些比较重要的创建worker进程的部分了:
//获取ngx_core_module模块的配置
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
//开启worker进程,相当于要执行fork了,ccf->worker_processes为需要开启的worker进程的数量
ngx_start_worker_processes(cycle, ccf->worker_processes,
NGX_PROCESS_RESPAWN);
ngx_start_cache_manager_processes(cycle, 0);
ngx_start_worker_processes函数用来创建worker进程,具体worker进程的数量在ngx_core_module模块的配置的worker_processes域存储。ngx_start_cache_manager_processes用来开启与cache相关的进程。
接下来分析ngx_start_worker_processes函数:
//开启worker进程
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; //通过channel传递过去的数据
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
ch.command = NGX_CMD_OPEN_CHANNEL; //命令
//这里的n是从配置文件中读取的,表示需要有多少个worker进程,那么就fork出来多少个worker进程
for (i = 0; i < n; i++) {
cpu_affinity = ngx_get_cpu_affinity(i);
//在这里创建work进程,ngx_worker_process_cycle为该woker进程的执行函数,执行函数的数据位空,
ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
"worker process", type);
//初始化ch的值,ngx_process_slot是刚刚fork出来的进程在ngx_processes数组中的位置
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
//将socketpair的chanel0,也就是写端的描述符传递给其他的进程
ch.fd = ngx_processes[ngx_process_slot].channel[0];
//向其他的worker传递channel
ngx_pass_open_channel(cycle, &ch);
}
}
这里有比较需要注意的地方是,通过一个n循环,调用n次ngx_spawn_process函数创建n个worker进程,在
ngx_spawn_process函数中会将刚刚建立的进程描述符存起来,这里又涉及到一个全局数组ngx_processes(定义在Ngx_process.c文件当中),它用来保存所有worker进程的一些信息,然后会创建一些chanel命令,用于命令以前已经建立的worker进程,让他们跟新socketpair的信息,这是用于进程间通信的,具体的以后再说吧。
这些都执行完了以后,就可以开始进入master进程的主循环了,其实master进程的主循环很是没有意思,说白了就是响应一些信号,调用sigsuspend函数等待信号,这里master进程的信号处理函数在main函数里面都已经初始化完成了,其实他们都是同一个信号处理函数ngx_signal_handler,定义在Ngx_process.c文件当中。该函数会判断接收到的信号,然后设置相应的参数,master进程的主循环就通过这些参数判断接受了哪些信号,然后进行相应的处理。
那么到这里就写完了master进程的,擦。。其实感觉好水,有些东西还是没有弄的太懂,就这样吧。。以后再弄,接下来的文章写worker进程吧