您的位置:首页 > 运维架构 > Nginx

nginx源码分析—全局变量ngx_cycle的初始化

2013-05-14 16:29 246 查看
作者:阿波

链接:/article/1451045.html

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结构图如下。



main()调用ngx_init_cycle()后,全局变量ngx_cycle的内容如下。可对比上图查看。

[plain] view
plaincopy

(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

[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()代码
省略,可自行研究。
/article/1451045.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: