// 监听链接数组初始化
n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
if (cycle->listening.elts == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->listening.nelts = 0;
cycle->listening.size = sizeof(ngx_listening_t);
cycle->listening.nalloc = n;
cycle->listening.pool = pool;
这段代码比较简单,主要是数组的创建和初始化操作
// nginx 复用连接队列初始化
ngx_queue_init(&cycle->reusable_connections_queue);
循环双向链表结构 -- ngx_queue_t
复用连接队列是一个循环双向链表结构 ngx_queue_t
typedef struct ngx_queue_s ngx_queue_t;
struct ngx_queue_s {
ngx_queue_t *prev;
ngx_queue_t *next;
};
这里有一点不明白,这样的结构,只有指针域,究竟是用来做什么的呢?
随着我们继续深入的研究源码,应该可以逐步解答这个问题
循环双向链表初始化 -- ngx_queue_init
#define ngx_queue_init(q) \
(q)->prev = q; \
(q)->next = q
这个宏函数很简单,就是让节点的前后指针都指向自己,这是一个典型的双向链表初始化方式
// struct ngx_module_s
// nginx 模块结构 {{{
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;
}; // }}}
// 创建所有模块的配置上下文数组
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if (module->create_conf) {
// 创建模块配置
rv = module->create_conf(cycle);
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[ngx_modules[i]->index] = rv;
}
}
// 初始化所有模块
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = ngx_modules[i]->ctx;
if (module->init_conf) {
if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
== NGX_CONF_ERROR)
{
environ = senv;
ngx_destroy_cycle_pools(&conf);
return NULL;
}
}
}
在内存池中分配了空间,用来存储所有模块的配置上下文数组的首地址
// 获取主机名
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);
这里使用系统调用 gethostname 将当前主机的 hostname 保存在局部变量 hostname 中,并赋值到 cycle->hostname 中
字符串拷贝并转换为小写 -- ngx_strlow
// void ngx_strlow(u_char *dst, u_char *src, size_t n)
// 内存拷贝,并转换成小写 {{{
void
ngx_strlow(u_char *dst, u_char *src, size_t n)
{
while (n) {
*dst = ngx_tolower(*src);
dst++;
src++;
n--;
}
} // }}}
这是一个非常常用的函数,在nginx中这个函数实现的非常简洁漂亮,值得学习