主要分析一下worker进程的情况。首先找到worker进程的入口-ngx_worker_process_cycle。这个函数不仅是worker进程的入口函数,而且是worker进程 循环工作的主要函数。
首先将全局变量ngx_process设置为worker进程的标志,然后调用ngx_worker_process_init,对worker进程作初始化操作。先看看worker进程的初始化过程。
if (ngx_set_environment(cycle, NULL) == NULL) {
/* fatal */
exit(2);
}
上面是设置相应的环境变量。接着就是设置一些资源的限制,id等参数。
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_process) {
if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
上面代码是循环调用每个模块的init_process,完成每个模块的进程初始化操作。调用init_process的模块比较少,只有ngx_event_process_init、ngx_google_perftools_worker、ngx_http_perl_init_worker、ngx_http_userid_init_worker。
for (n = 0; n < ngx_last_process; n++) {
if (ngx_processes[n].pid == -1) {
continue;
}
if (n == ngx_process_slot) {
continue;
}
if (ngx_processes[n].channel[1] == -1) {
continue;
}
if (close(ngx_processes[n].channel[1]) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"close() channel failed");
}
}
上面代码主要是关闭其它进程的channel资源。
if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"close() channel failed");
}
因为worker进程主要是读取master进程发过来的消息,所以worker进程关闭本进程的写通道,只保留读通道。
if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
ngx_channel_handler)
== NGX_ERROR)
{
/* fatal */
exit(2);
}
将本worker进程的读通道加入到nginx关心的集合中,即读通道上有数据到来后,就作相应的读操作。
此处初始化结束。
for ( ;; ) {
if (ngx_exiting) {
c = cycle->connections;
for (i = 0; i < cycle->connection_n; i++) {
/* THREAD: lock */
if (c[i].fd != -1 && c[i].idle) {
c[i].close = 1;
c[i].read->handler(c[i].read);
}
}
if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
{
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
ngx_worker_process_exit(cycle);
}
}
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
ngx_process_events_and_timers(cycle);
if (ngx_terminate) {
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
ngx_worker_process_exit(cycle);
}
if (ngx_quit) {
ngx_quit = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"gracefully shutting down");
ngx_setproctitle("worker process is shutting down");
if (!ngx_exiting) {
ngx_close_listening_sockets(cycle);
ngx_exiting = 1;
}
}
if (ngx_reopen) {
ngx_reopen = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
ngx_reopen_files(cycle, -1);
}
}
ngx_exiting是在worker进程收到SIGQUIT信号后,在worker进程退出前,处理完每个connection上发生的事件,处理完成后,进程退出。
ngx_process_events_and_timers是进程处理事件的核心。
ngx_ternimate是worker进程收到SIGINT信号后,进程退出。
ngx_quit是进程收到SIGQUIT信号,如果此时worker进程不是处于exiting状态,就将ngx_exiting设置为1,让其进入exiting状态,同时关闭监听套接口。
ngx_reopen是进程收到SIGUSR1信号。
worker进程的处理流程差不多就是这样了。