ngx_cycle_init的实现

来源:互联网 发布:fifa18数据库 编辑:程序博客网 时间:2024/05/21 09:18

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
关闭多余的打开文件

0 0
原创粉丝点击