作者:阿波
链接: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文件中定义,如下。
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。
其中,
各种数据结构关系图如下。
2. ngx_init_cycle()分析
初始化过程如下。
具体请参考附录代码,不需要细究每一步实现,重要的是要搞清楚其初始化流程。
简要的函数调用图如下。图的自动生成,可参考<用Graphviz可视化函数调用-使用开源软件来简化复杂调用结构>。
初始化过程中全局结构ngx_cycle结构图如下。
main()调用ngx_init_cycle()后,全局变量ngx_cycle的内容如下。可对比上图查看。
(gdb) p *ngx_cycle $3 = { conf_ctx = 0x6b1060, pool = 0x6b0280, log = 0x6b02e8, new_log = { log_level = 4, file = 0x6b0558, connection = 0, handler = 0, data = 0x0, action = 0x0 }, files = 0x0, free_connections = 0x0, free_connection_n = 0, reusable_connections_queue = { prev = 0x6b0330, next = 0x6b0330 }, listening = { elts = 0x6b0930, nelts = 1, size = 184, nalloc = 10, pool = 0x6b0280 }, pathes = { elts = 0x6b04d8, nelts = 5, size = 8, nalloc = 10, pool = 0x6b0280 }, open_files = { last = 0x6b0398, part = { elts = 0x6b0528, nelts = 2, next = 0x0 ---Type <return> to continue, or q <return> to quit--- }, size = 48, nalloc = 20, pool = 0x6b0280 }, shared_memory = { last = 0x6b03d0, part = { elts = 0x6b08e8, nelts = 0, next = 0x0 }, size = 72, nalloc = 1, pool = 0x6b0280 }, connection_n = 1024, files_n = 0, connections = 0x0, read_events = 0x0, write_events = 0x0, old_cycle = 0x0, conf_file = { len = 32, data = 0x6b04b7 "/usr/local/nginx/conf/nginx.conf" }, conf_param = { len = 0, data = 0x6b04d8 "\240{l" }, conf_prefix = { len = 22, data = 0x6b0490 "/usr/local/nginx/conf//usr/local/nginx//usr/local/nginx/conf/nginx.conf" }, prefix = { len = 17, data = 0x6b04a6 "/usr/local/nginx//usr/local/nginx/conf/nginx.conf" }, lock_file = { ---Type <return> to continue, or q <return> to quit--- len = 33, data = 0x6ccee0 "/usr/local/nginx/logs/nginx.lock.accept" }, hostname = { len = 4, data = 0x6b11c0 "yu30" } }
3.注意问题
3.1如何调用CORE模块的callback函数?
即如可调用core模块的create_conf()和init_conf()?
(1) callback定义
file: ./src/core/ngx_conf_file.h
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
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
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()代码
省略,可自行研究。