您的位置:首页 > 其它

ngx_cycle_init的实现

2016-04-15 13:46 260 查看
main函数主要完成的是对ngx_cycle_t结构体变量的一个初始化

ngx_cycle_t * cycle ,init_cycle

cycle=ngx_cycle_init(&init_cycle)

流程:

调用ngx_timezone_update()更新时区,调用ngx_time_update()更新时间

创建大小为NGX_CYCLE_POOL_SIZE=16384B的内存池,并从中分配ngx_cycle_t结构

简单初始化,如记录pool指针、log指针

初始化配置前缀、前缀、配置文件、配置参数等字符串

初始化pathes数组//在初始化一下四个变量的时候采取的方式都是如果旧的cycle有就把它赋值给新的cycle,如果没有的话就采取默认值的方式

初始化open_files链表

初始化shared_memory链表

初始化listening数组

初始化resuable_connections_queue队列

从pool为conf_ctx分配空间

cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));

初始化hostname字符串,通过gethostname()

调用core模块的create_conf()

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);  //create_conf返回的是ngx_core_conf_t结构体
if (rv == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->conf_ctx[ngx_modules[i]->index] = rv;
}


}

虽然有很多个核心模块,但是只有俩个模块实现了create_conf,而且最主要的就是ngx_core_module。用于存储整个配置文件main scope作用域内的信息,不属于任何模块的,比如worker_process

配置文件解析

ngx_memzero(&conf, sizeof(ngx_conf_t));

conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); // args是指令后带的参数的数组

if (conf.args == NULL) {

ngx_destroy_pool(pool);

return NULL;

}

conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);

if (conf.temp_pool == NULL) {

ngx_destroy_pool(pool);

return NULL;

}

/* 解析core module对应的指令,此时conf的上下文是cycle->conf_ctx,就是所有core module的config信息 */

conf.ctx = cycle->conf_ctx;

conf.cycle = cycle;

conf.pool = pool;

conf.log = log;

conf.module_type = NGX_CORE_MODULE; // conf.module_type指示将要解析这个类型模块的指令。

conf.cmd_type = NGX_MAIN_CONF; // conf.cmd_type指示将要解析的指令的类型。

这段代码用于解析配置文件,ngx_conf_t是用于保存解析出来的配置文件的,conf->arg0是指令名,conf->arg1-argn是指令参数,默认是申请10个,参数个数需要根据ngx_command_t中的type属性做校验,conf的module_type=NGX_HTTP_MODULE,而cmd_type=NGX_HTTP_SRV_CONF,表示在一次配置文件的解析过程中只会对http模块的server指令做解析

[plain] view plain copy print?

if (ngx_conf_param(&conf) != NGX_CONF_OK) {

environ = senv;

ngx_destroy_cycle_pools(&conf);

return NULL;

} //对全局配置指令做解析,比如./nginx -g

if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {

environ = senv;

ngx_destroy_cycle_pools(&conf);

return NULL;

}

nginx的指令分为块指令和普通指令,块指令负责调用ngx_conf_parse函数解析块内指令,注意该函数是一个递归调用的函数,等到它调用完毕以后,所有的指令也都解析完毕,具体的配置文件的解析看配置文件解析的一节

调用core模块的init_conf()

该函数用于对ngx_core_conf_t中没有被赋值的字段设置默认值

遍历open_files链表中的每一个文件并打开

创建共享内存并初始化(新旧shared_memory链表的比较,相同的共享内存保留,旧的不同的共享内存被释放,新的被创建)

接下来是处理新旧监听套接口,把新旧的socket进行合并

if (ngx_open_listening_sockets(cycle) != NGX_OK) {

goto failed;

}

(尝试5遍)遍历listening数组并打开所有侦听sockets(socket()->setsockopt()->bind()->listen())即调用socket创建套接字,调用setsockopt设置为可重用socket(通过setsockopt()设置,本地的端口加ip可以多次和不同的对端建立连接,这就是重用的意义),设置非阻塞socket(通过recv()函数的参数设置),调用bind绑定,调用listen转化为监听socket

ngx_configure_listening_sockets(cycle); 根据cycle配置所有监听的套接口,包括设置监听socket的接收缓冲区大小等

pool->log = cycle->log;

// 提交新的cycle配置,

// 并调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)

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);

}

}

}

提交新的cycle配置,并调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)

关闭或删除残留在old_cycle中的资源

释放多余的共享内存

关闭多余的侦听sockets

关闭多余的打开文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: