作者:阿波
链接:http://blog.csdn.net/livelylittlefish/article/details/7247080
Content
0.序
1. ngx_cycle_t结构
2. ngx_init_cycle()分析
3.注意问题
3.1如何调用CORE模块的callback函数?
3.2 open_files链表中的文件名何时初始化?
4.小结
0.序
Nginx的大部分初始化工作主要围绕一个类型为ngx_cycle_t类型的全局变量(cycle)展开。本文重点介绍全局变量ngx_cycle的初始化。
实现文件:./src/core/ngx_cycle.c。.表示nginx-1.0.4代码目录,本文为/usr/src/nginx-1.0.4。
1. ngx_cycle_t结构
该结构在./src/core/ngx_cycle.h文件中定义,如下。
[cpp] view plaincopy
struct ngx_cycle_s {
void ****conf_ctx; //配置上下文数组(含所有模块)
ngx_pool_t *pool; //内存池
ngx_log_t *log; //日志
ngx_log_t new_log;
ngx_connection_t **files; //连接文件
ngx_connection_t *free_connections; //空闲连接
ngx_uint_t free_connection_n; //空闲连接个数
ngx_queue_t reusable_connections_queue; //再利用连接队列
ngx_array_t listening; //监听数组
ngx_array_t pathes; //路径数组
ngx_list_t open_files; //打开文件链表
ngx_list_t shared_memory; //共享内存链表
ngx_uint_t connection_n; //连接个数
ngx_uint_t files_n; //打开文件个数
ngx_connection_t *connections; //连接
ngx_event_t *read_events; //读事件
ngx_event_t *write_events; //写事件
ngx_cycle_t *old_cycle; //old cycle指针
ngx_str_t conf_file; //配置文件
ngx_str_t conf_param; //配置参数
ngx_str_t conf_prefix; //配置前缀
ngx_str_t prefix; //前缀
ngx_str_t lock_file; //锁文件
ngx_str_t hostname; //主机名
};
该结构体的大小是确定的,sizeof(ngx_cycle_t)=224。
其中,
pathes数组元素结构为ngx_path_t;
open_files链表元素结构为ngx_open_file_t;
shared_memory链表元素结构为ngx_shm_zone_t;
listening数组元素结构为ngx_listening_t,该数组用来存放监听套接字。
各种数据结构关系图如下。
2. ngx_init_cycle()分析
初始化过程如下。
调用ngx_timezone_update()更新时区,调用ngx_time_update()更新时间
创建大小为NGX_CYCLE_POOL_SIZE=16384B的内存池,并从中分配ngx_cycle_t结构
简单初始化,如记录pool指针、log指针
初始化配置前缀、前缀、配置文件、配置参数等字符串
初始化pathes数组
初始化open_files链表
初始化shared_memory链表
初始化listening数组
初始化resuable_connections_queue队列
从pool为conf_ctx分配空间
初始化hostname字符串
调用core模块的create_conf()
配置文件解析
调用core模块的init_conf()
遍历open_files链表中的每一个文件并打开
创建共享内存并初始化(新旧shared_memory链表的比较,相同的共享内存保留,旧的不同的共享内存被释放,新的被创建)
(尝试5遍)遍历listening数组并打开所有侦听sockets(socket()->setsockopt()->bind()->listen())
提交新的cycle配置,并调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)
关闭或删除残留在old_cycle中的资源
释放多余的共享内存
关闭多余的侦听sockets
关闭多余的打开文件
具体请参考附录代码,不需要细究每一步实现,重要的是要搞清楚其初始化流程。
简要的函数调用图如下。图的自动生成,可参考<用Graphviz可视化函数调用-使用开源软件来简化复杂调用结构>。
初始化过程中全局结构ngx_cycle结构图如下。
3.注意问题
3.1如何调用CORE模块的callback函数?
即如可调用core模块的create_conf()和init_conf()?
(1) callback定义
file: ./src/core/ngx_conf_file.h
[cpp] view plaincopy
typedef struct { //定义core模块上下文类型
ngx_str_t name; //模块名,即ngx_core_module_ctx结构体对象的ngx_string("core")
void *(*create_conf)(ngx_cycle_t *cycle); //创建配置的callback
char *(*init_conf)(ngx_cycle_t *cycle, void *conf); //初始化配置的callback
} ngx_core_module_t;
(2) callback初始化
静态初始化ngx_core_module_ctx和ngx_core_module结构。在编译期间就已确定CORE模块的callback了。
file: ./src/core/nginx.c
[cpp] view plaincopy
static ngx_core_module_t ngx_core_module_ctx = { //定义ngx_core_module模块上下文,改方式属于静态初始化
ngx_string("core"),
ngx_core_module_create_conf,
ngx_core_module_init_conf
};
ngx_module_t ngx_core_module = { //定义ngx_core_module模块,也是静态初始化
NGX_MODULE_V1,
&ngx_core_module_ctx, /* module context */
ngx_core_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
静态初始化ngx_core_commands结构。
file: ./src/core/nginx.c
[cpp] view plaincopy
static ngx_command_t ngx_core_commands[] = { //静态初始化core模块的命令
{ ngx_string("daemon"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
0,
offsetof(ngx_core_conf_t, daemon),
NULL },
{ ngx_string("master_process"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
0,
offsetof(ngx_core_conf_t, master),
NULL },
{ ngx_string("timer_resolution"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
0,
offsetof(ngx_core_conf_t, timer_resolution),
NULL },
{ ngx_string("pid"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_core_conf_t, pid),
NULL },
{ ngx_string("lock_file"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_core_conf_t, lock_file),
NULL },
{ ngx_string("worker_processes"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_core_conf_t, worker_processes),
NULL },
/* ... 省略中间的定义*/
#if (NGX_THREADS)
{ ngx_string("worker_threads"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_core_conf_t, worker_threads),
NULL },
{ ngx_string("thread_stack_size"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
0,
offsetof(ngx_core_conf_t, thread_stack_size),
NULL },
#endif
ngx_null_command
};
3.2 open_files链表中的文件名何时初始化?
在初始化open_files链表之后遍历该链表并打开文件之前,并未看到向open_files链表中写入文件名。那么,何时写入open_files链表的?
——在ngx_conf_open_file函数中写入。
具体请参考源代码。打开文件后,open_files链表就保存了ngx_open_file_t结构的数据,具体请参考该结构定义。
4.小结
本文主要分析ngx_cycle的初始化,后文继续分析其中调用的CORE模块的callback和配置文件解析等。
Appendix: ngx_init_cycle()代码
[cpp] view plaincopy
ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
void *rv;
char **senv, **env;
ngx_uint_t i, n;
ngx_log_t *log;
ngx_time_t *tp;
ngx_conf_t conf;
ngx_pool_t *pool;
ngx_cycle_t *cycle, **old;
ngx_shm_zone_t *shm_zone, *oshm_zone;
ngx_list_part_t *part, *opart;
ngx_open_file_t *file;
ngx_listening_t *ls, *nls;
ngx_core_conf_t *ccf, *old_ccf;
ngx_core_module_t *module;
char hostname[NGX_MAXHOSTNAMELEN];
ngx_timezone_update(); /*更新时区*/
/* force localtime update with a new timezone */
tp = ngx_timeofday();
tp->sec = 0;
ngx_time_update(); /*更新时间*/
log = old_cycle->log;
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); /*创建大小为16384B的内存池*/
if (pool == NULL) {
return NULL;
}
pool->log = log;
cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); /*在该内存池上分配大小为224B的空间存放ngx_cycle_t结构*/
if (cycle == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/* 以下的初始化就是为了填满上述分配的ngx_cycle_t结构*/
cycle->pool = pool; /*一些简单的初始化*/
cycle->log = log;
cycle->new_log.log_level = NGX_LOG_ERR;
cycle->old_cycle = old_cycle;
/** 以下对配置前缀、前缀、配置文件、配置参数等字符串进行初始化
注意:此处对conf_prefix, prefix, conf_file, conf_param的初始化均是从old_cycle同名字段拷贝而来,
而old_cycle中的这些字段的初始化是在main函数中调用ngx_init_cycle()函数前调用ngx_process_options()完成
*/
cycle->conf_prefix.len = old_cycle->conf_prefix.len;
cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);
if (cycle->conf_prefix.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->prefix.len = old_cycle->prefix.len;
cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix);
if (cycle->prefix.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_file.len = old_cycle->conf_file.len;
cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
if (cycle->conf_file.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,
old_cycle->conf_file.len + 1);
cycle->conf_param.len = old_cycle->conf_param.len;
cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);
if (cycle->conf_param.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/* 以下初始化pathes数组(实际上,在计算出n后,可以调用ngx_array_init()进行初始化) */
/*先初始化pathes数组元素个数*/
n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;
/*为pathes数组分配空间(从pool指向的内存池)*/
cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
if (cycle->pathes.elts == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/*初始化pathes数组的各字段*/
cycle->pathes.nelts = 0;
cycle->pathes.size = sizeof(ngx_path_t *); /*该字段为pathes数组中每个元素的大小*/
cycle->pathes.nalloc = n;
cycle->pathes.pool = pool;
/* 以下初始化open_files链表*/
/*先初始化open_files链表中所有元素个数*/
if (old_cycle->open_files.part.nelts) {
n = old_cycle->open_files.part.nelts;
for (part = old_cycle->open_files.part.next; part; part = part->next) {
n += part->nelts;
}
} else {
n = 20; /*若改链表中没有元素,则默认赋值为20*/
}
/*初始化open_files链表(将从pool指向的内存池分配数组元素空间并进行链表字段的初始化)*/
if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
/* 以下初始化shared_memory链表*/
/*先初始化shared_memory链表元素个数*/
if (old_cycle->shared_memory.part.nelts) {
n = old_cycle->shared_memory.part.nelts;
for (part = old_cycle->shared_memory.part.next; part; part = part->next)
{
n += part->nelts;
}
} else {
n = 1; /*若改链表中没有元素,则默认赋值为1*/
}
/*初始化shared_memory链表(将从pool指向的内存池分配数组元素空间并进行链表字段的初始化)*/
if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
}
/* 以下初始化listening数组(实际上,在计算出n后,可以调用ngx_array_init()进行初始化) */
/*先初始化listening数组元素个数*/
n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
/*为listening数组分配空间(从pool指向的内存池)*/
cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
if (cycle->listening.elts == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/*初始化listening数组的各字段*/
cycle->listening.nelts = 0;
cycle->listening.size = sizeof(ngx_listening_t);
cycle->listening.nalloc = n;
cycle->listening.pool = pool;
/*初始化reusable_connections_queue队列*/
ngx_queue_init(&cycle->reusable_connections_queue);
/*从pool为conf_ctx分配空间*/
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/* 以下初始化hostname字符串*/
if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");
ngx_destroy_pool(pool);
return NULL;
}
/* on Linux gethostname() silently truncates name that does not fit */
hostname[NGX_MAXHOSTNAMELEN - 1] = '/0';
cycle->hostname.len = ngx_strlen(hostname);
cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);
if (cycle->hostname.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);
/* 调用core模块的create_conf() */
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_CORE_MODULE) { /* 仅处理CORE模块*/
continue;
}
module = ngx_modules[i]->ctx; /*即ngx_core_module_ctx结构*/
if (module->create_conf) { /*create_conf是core模块的callback*/
rv = module->create_conf(cycle); /*即调用ngx_core_module_create_conf*/
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[ngx_modules[i]->index] = rv; /*保存该配置结构*/
}
}
senv = environ;
/*初始化conf.args数组, 10*8=80B*/
ngx_memzero(&conf, sizeof(ngx_conf_t));
/* STUB: init array ? */
conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
if (conf.args == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/*创建大小为16384B的内存池, 由conf.temp_pool记录*/
conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
if (conf.temp_pool == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
/*初始化conf的其他字段,conf是一个局部对象(ngx_conf_t结构体)*/
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
conf.log = log;
conf.module_type = NGX_CORE_MODULE;
conf.cmd_type = NGX_MAIN_CONF;
#if 0
log->log_level = NGX_LOG_DEBUG_ALL;
#endif
/*配置参数*/
if (ngx_conf_param(&conf) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
/*配置文件解析*/
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
if (ngx_test_config && !ngx_quiet_mode) {
ngx_log_stderr(0, "the configuration file %s syntax is ok",
cycle->conf_file.data);
}
/* 调用core模块的init_conf() */
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_CORE_MODULE) { /* 仅处理CORE模块*/
continue;
}
module = ngx_modules[i]->ctx; /*即ngx_core_module_ctx结构*/
if (module->init_conf) { /*init_conf是core模块的callback*/
if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
== NGX_CONF_ERROR) /*即调用ngx_core_module_init_conf*/
{
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
}
}
if (ngx_process == NGX_PROCESS_SIGNALLER) {
return cycle;
}
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
if (ngx_test_config) {
if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {
goto failed;
}
} else if (!ngx_is_init_cycle(old_cycle)) {
/*
* we do not create the pid file in the first ngx_init_cycle() call
* because we need to write the demonized process pid
*/
old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,
ngx_core_module);
if (ccf->pid.len != old_ccf->pid.len
|| ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0)
{
/* new pid file name */
if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { /*创建pid文件*/
goto failed;
}
ngx_delete_pidfile(old_cycle);
}
}
if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) {
goto failed;
}
if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) {
goto failed;
}
if (cycle->new_log.file == NULL) {
cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); /* 该函数向open_files链表写入数据*/
if (cycle->new_log.file == NULL) {
goto failed;
}
}
/* open the new files */
part = &cycle->open_files.part;
file = part->elts;
/* 该循环遍历open_files链表*/
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
file = part->elts;
i = 0;
}
if (file[i].name.len == 0) {
continue;
}
/* 打开当前文件file[i] */
file[i].fd = ngx_open_file(file[i].name.data,
NGX_FILE_APPEND,
NGX_FILE_CREATE_OR_OPEN,
NGX_FILE_DEFAULT_ACCESS);
ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,
"log: %p %d /"%s/"",
&file[i], file[i].fd, file[i].name.data);
if (file[i].fd == NGX_INVALID_FILE) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
ngx_open_file_n " /"%s/" failed",
file[i].name.data);
goto failed;
}
#if !(NGX_WIN32)
if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"fcntl(FD_CLOEXEC) /"%s/" failed",
file[i].name.data);
goto failed;
}
#endif
}
cycle->log = &cycle->new_log;
pool->log = &cycle->new_log;
/* create shared memory */
part = &cycle->shared_memory.part;
shm_zone = part->elts;
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
shm_zone = part->elts;
i = 0;
}
if (shm_zone[i].shm.size == 0) {
ngx_log_error(NGX_LOG_EMERG, log, 0,
"zero size shared memory zone /"%V/"",
&shm_zone[i].shm.name);
goto failed;
}
if (shm_zone[i].init == NULL) {
/* unused shared zone */
continue;
}
shm_zone[i].shm.log = cycle->log;
/* 与旧的shared_memory一一比较,将相同的保留,不相同的释放*/
opart = &old_cycle->shared_memory.part;
oshm_zone = opart->elts;
for (n = 0; /* void */ ; n++) {
if (n >= opart->nelts) {
if (opart->next == NULL) {
break;
}
opart = opart->next;
oshm_zone = opart->elts;
n = 0;
}
if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {
continue;
}
if (ngx_strncmp(shm_zone[i].shm.name.data,
oshm_zone[n].shm.name.data,
shm_zone[i].shm.name.len)
!= 0)
{
continue;
}
if (shm_zone[i].shm.size == oshm_zone[n].shm.size) {
shm_zone[i].shm.addr = oshm_zone[n].shm.addr;
if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data)
!= NGX_OK)
{
goto failed;
}
goto shm_zone_found; /* 相同的共享内存被保留*/
}
/* 与&cycle->shared_memory不相同的共享内存被释放*/
ngx_shm_free(&oshm_zone[n].shm);
break;
}
/* 以下创建共享内存并初始化*/
if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {
goto failed;
}
if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {
goto failed;
}
if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {
goto failed;
}
shm_zone_found:
continue;
}
/* handle the listening sockets */
if (old_cycle->listening.nelts) { /* 旧listening数组有元素时*/
ls = old_cycle->listening.elts;
for (i = 0; i < old_cycle->listening.nelts; i++) {
ls[i].remain = 0;
}
/* 新旧listening数组比较*/
nls = cycle->listening.elts;
for (n = 0; n < cycle->listening.nelts; n++) {
for (i = 0; i < old_cycle->listening.nelts; i++) {
if (ls[i].ignore) {
continue;
}
/* 主要比较新旧listening数组元素的sockaddr字段,并根据比较结果对sockets相关字段赋值*/
if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK)
{
nls[n].fd = ls[i].fd;
nls[n].previous = &ls[i];
ls[i].remain = 1;
if (ls[n].backlog != nls[i].backlog) {
nls[n].listen = 1;
}
/* 中间省略一些代码*/
break;
}
}
if (nls[n].fd == -1) {
nls[n].open = 1;
}
}
} else { /* 旧listening数组没有元素时*/
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
ls[i].open = 1;
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
if (ls[i].accept_filter) {
ls[i].add_deferred = 1;
}
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
if (ls[i].deferred_accept) {
ls[i].add_deferred = 1;
}
#endif
}
}
/* 遍历listening数组并打开socket */
if (ngx_open_listening_sockets(cycle) != NGX_OK) {
goto failed;
}
if (!ngx_test_config) {
ngx_configure_listening_sockets(cycle);
}
/* commit the new cycle configuration */
if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) {
if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
ngx_set_stderr_n " failed");
}
}
pool->log = cycle->log;
/* 调用所有模块的init_module,实际上只有ngx_event_core_module模块使用了该callback */
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_module) {
if (ngx_modules[i]->init_module(cycle) != NGX_OK) {
/* fatal */
exit(1);
}
}
}
/* close and delete stuff that lefts from an old cycle */
/* free the unnecessary shared memory */
/* 中间省略一些代码*/
old_shm_zone_done:
/* 中间省略一些代码*/
/* close the unnecessary open files */
/* 中间省略一些代码*/
ngx_destroy_pool(conf.temp_pool); /* 销毁临时内存池*/
if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) {
/*
* perl_destruct() frees environ, if it is not the same as it was at
* perl_construct() time, therefore we save the previous cycle
* environment before ngx_conf_parse() where it will be changed.
*/
env = environ;
environ = senv;
ngx_destroy_pool(old_cycle->pool);
cycle->old_cycle = NULL;
environ = env;
return cycle;
}
if (ngx_temp_pool == NULL) {
ngx_temp_pool = ngx_create_pool(128, cycle->log);
if (ngx_temp_pool == NULL) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"can not create ngx_temp_pool");
exit(1);
}
n = 10;
ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,
n * sizeof(ngx_cycle_t *));
if (ngx_old_cycles.elts == NULL) {
exit(1);
}
ngx_old_cycles.nelts = 0;
ngx_old_cycles.size = sizeof(ngx_cycle_t *);
ngx_old_cycles.nalloc = n;
ngx_old_cycles.pool = ngx_temp_pool;
ngx_cleaner_event.handler = ngx_clean_old_cycles; /*在定时器事件中被调用来清理资源*/
ngx_cleaner_event.log = cycle->log;
ngx_cleaner_event.data = &dumb;
dumb.fd = (ngx_socket_t) -1;
}
ngx_temp_pool->log = cycle->log;
old = ngx_array_push(&ngx_old_cycles);
if (old == NULL) {
exit(1);
}
*old = old_cycle;
if (!ngx_cleaner_event.timer_set) {
ngx_add_timer(&ngx_cleaner_event, 30000); /*设定清理定时器,每30000ms清理一次*/
ngx_cleaner_event.timer_set = 1;
}
return cycle;
failed:
/* 中间省略一些代码*/ (免责声明:文章内容如涉及作品内容、版权和其它问题,请及时与我们联系,我们将在第一时间删除内容,文章内容仅供参考)