对于单进程方式
调用ngx_single_process_cycle来初始化进程及socket模型
对于多线程模式,调用ngx_master_process_cycle初始化主线程
先看看单线程模型:
ngx_single_process_cycle位于src/os/win32/ngx_process_cycle.c主要代码在工作线程ngx_worker_thread里面,如下:
static ngx_thread_value_t __stdcall
ngx_worker_thread(void *data)
{
ngx_int_t n;
ngx_uint_t i;
ngx_cycle_t *cycle;
ngx_connection_t *c;
cycle = (ngx_cycle_t *) ngx_cycle;
for (n = 0; ngx_modules[n]; n++) {
if (ngx_modules[n]->init_process) {
if (ngx_modules[n]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
while (!ngx_quit) {
if (ngx_exiting) {
c = cycle->connections;
for (i = 0; i < cycle->connection_n; i++) {
/* THREAD: lock */
if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) {
c[i].close = 1;
c[i].read->handler(c[i].read);
}
}
ngx_event_cancel_timers();
if (ngx_event_timer_rbtree.root
== ngx_event_timer_rbtree.sentinel)
{
break;
}
}
ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "worker cycle");
ngx_process_events_and_timers(cycle);
if (ngx_terminate) {
return 0;
}
if (ngx_quit) {
ngx_quit = 0;
if (!ngx_exiting) {
ngx_close_listening_sockets(cycle);
ngx_exiting = 1;
}
}
if (ngx_reopen) {
ngx_reopen = 0;
ngx_reopen_files(cycle, -1);
}
}
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
return 0;
}
其中关键是调用init_process,init_process是struct ngx_module_s里面的一个成员。
ngx_module_s定义如下:
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t spare2;
ngx_uint_t spare3;
ngx_uint_t version;
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
init_process作为指针指向的实际上是函数static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle);该函数位于 src/event/ngx_event.c。
疑点在于ngx_event_process_init何时初始化给init_process,答案是在ngx_event.c中声明了一个全局变量:
ngx_module_t ngx_event_core_module = {
NGX_MODULE_V1,
&ngx_event_core_module_ctx, /* module context */
ngx_event_core_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
NULL, /* init master */
ngx_event_module_init, /* init module */
ngx_event_process_init, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
这里对socket模型进行初始化
if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
/* fatal */
exit(2);
}
详细代码如下
static ngx_int_t ngx_iocp_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
ngx_iocp_conf_t *cf;
cf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module);
if (iocp == NULL) {
iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0,
cf->threads);
}
if (iocp == NULL) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"CreateIoCompletionPort() failed");
return NGX_ERROR;
}
ngx_io = ngx_iocp_io;
ngx_event_actions = ngx_iocp_module_ctx.actions;
ngx_event_flags = NGX_USE_AIO_EVENT|NGX_USE_IOCP_EVENT;
if (timer == 0) {
return NGX_OK;
}
/*
* The waitable timer could not be used, because
* GetQueuedCompletionStatus() does not set a thread to alertable state
*/
if (timer_thread == NULL) {
msec = timer;
if (ngx_create_thread(&timer_thread, ngx_iocp_timer, &msec, cycle->log)
!= 0)
{
return NGX_ERROR;
}
}
ngx_event_flags |= NGX_USE_TIMER_EVENT;
return NGX_OK;
}
init的初始化也是通过声明全局结构体的方式,在ngx_iocp_module.c里面,如下
ngx_event_module_t ngx_iocp_module_ctx = {
&iocp_name,
ngx_iocp_create_conf, /* create configuration */
ngx_iocp_init_conf, /* init configuration */
{
ngx_iocp_add_event, /* add an event */
NULL, /* delete an event */
NULL, /* enable an event */
NULL, /* disable an event */
NULL, /* add an connection */
ngx_iocp_del_connection, /* delete an connection */
NULL, /* process the changes */
ngx_iocp_process_events, /* process the events */
ngx_iocp_init, /* init the events */
ngx_iocp_done /* done the events */
}
};
这里面初始化的其他处理函数在后面会用到。
首先调用CreateIoCompletionPort创建IOCP对象,然后调用ngx_create_thread创建多个线程,并纳入到IOCP的线程池中。