标签:
master进程模型核心函数ngx_master_process_cycle()中调用了创建子进程函数ngx_start_worker_processes(),该函数源码如下
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_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
ch.command = NGX_CMD_OPEN_CHANNEL;
/
for (i = 0; i < n; i++) {
/*ngx_spawn_process方法调用fork函数创建进程执行ngx_worker_process_cycle()函数,该函数是worker进程模型的核心*/
ngx_spawn_process(cycle, ngx_worker_process_cycle,
(void *) (intptr_t) i, "worker process", type);
/*
在ngx_spawn_process创建好一个worker进程返回后,master进程就将worker进程的pid、worker
进程在ngx_processes数组中的位置及channel[0]传递给前面已经创建好的worker进程,然后继续
循环开始创建下一个worker进程。
*/
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
ngx_pass_open_channel(cycle, &ch);
}
}
在剖析ngx_worker_process_cycle是如何工作的之前我们了解master进程和worker进程之间的通信方式:master进程是监控进程,对worker进程监控和管理,master进程采用的是信号管理worker进程。worker进程收到信号时,信号处理函数ngx_signal_handler()就会执行。
对于worker进程的工作方法ngx_worker_process_cycle来说,它主要关注4个全局标志位:
sig_atomic_t ngx_terminate; //强制关闭进程
sig_atomic_t ngx_quit; //优雅地关闭进程(有唯一一段代码会设置它,就是接受到QUIT信号。ngx_quit只有在首次设置为1,时,才会将ngx_exiting置为1)
ngx_uint_t ngx_exiting; //退出进程标志位
sig_atomic_t ngx_reopen; //重新打开所有文件
其中ngx_terminate、ngx_quit 、ngx_reopen都将由ngx_signal_handler根据接受到的信号来设置,如下表所示。ngx_exiting标志位仅由ngx_worker_cycle方法在退出时作为标志位使用。
|
信号 |
对应进程中全局标志位变量 |
意义 |
|
QUIT |
ngx_quit |
优雅关闭进程 |
|
TERM或者INT |
ngx_terminate |
强制关闭进程 |
|
USR1 |
ngx_reopen |
重新打开所有文件 |
现在我们来剖析ngx_worker_process_cycle()函数,可以对照下图来理解源代码:
static void
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
ngx_int_t worker = (intptr_t) data;
ngx_uint_t i;
ngx_connection_t *c;
ngx_process = NGX_PROCESS_WORKER;
/*worker进程进入工作循环之前的初始化工作*/
ngx_worker_process_init(cycle, worker);
ngx_setproctitle("worker process");
#if (NGX_THREADS)
{
ngx_int_t n;
ngx_err_t err;
ngx_core_conf_t *ccf;
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
if (ngx_threads_n) {
if (ngx_init_threads(ngx_threads_n, ccf->thread_stack_size, cycle)
== NGX_ERROR)
{
/* fatal */
exit(2);
}
err = ngx_thread_key_create(&ngx_core_tls_key);
if (err != 0) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
ngx_thread_key_create_n " failed");
/* fatal */
exit(2);
}
for (n = 0; n < ngx_threads_n; n++) {
ngx_threads[n].cv = ngx_cond_init(cycle->log);
if (ngx_threads[n].cv == NULL) {
/* fatal */
exit(2);
}
if (ngx_create_thread((ngx_tid_t *) &ngx_threads[n].tid,
ngx_worker_thread_cycle,
(void *) &ngx_threads[n], cycle->log)
!= 0)
{
/* fatal */
exit(2);
}
}
}
}
#endif
for ( ;; ) {
/*ngx_exiting为1,在开始准备关闭worker金曾*/
if (ngx_exiting) {
c = cycle->connections;
for (i = 0; i < cycle->connection_n; i++) {
/* THREAD: lock */
/* 根据当前ngx_cycle_t中所有正在处理的连接,调用它们对应的关闭连接处理方法 */
if (c[i].fd != -1 && c[i].idle) {
c[i].close = 1;
c[i].read->handler(c[i].read);
}
}
/*
若ngx_event_timer_rbtree红黑树不为空表示还有事件需要处理,
否则,调用ngx_worker_process_exit,以调用所有模块的exit_process方法,销毁内存池
*/
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");
/*调用所有模块的exit_process方法,销毁内存池*/
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_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);
}
}
}
转载请注明出处,谢谢~~
标签:
原文地址:http://blog.csdn.net/walkerkalr/article/details/38168477