Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1509599
  • 博文数量: 228
  • 博客积分: 1698
  • 博客等级: 上尉
  • 技术积分: 3241
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-24 21:49
个人简介

Linux

文章分类

全部博文(228)

文章存档

2017年(1)

2016年(43)

2015年(102)

2014年(44)

2013年(5)

2012年(30)

2011年(3)

分类: LINUX

2015-09-23 18:14:17

链接: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文件中定义,如下。

点击(此处)折叠或打开

  1. struct ngx_cycle_s {
  2.     void ****conf_ctx; //配置上下文数组(含所有模块)
  3.     ngx_pool_t *pool; //内存池
  4.   
  5.     ngx_log_t *log; //日志
  6.     ngx_log_t new_log;
  7.   
  8.     ngx_connection_t **files; //连接文件
  9.     ngx_connection_t *free_connections; //空闲连接
  10.     ngx_uint_t free_connection_n; //空闲连接个数
  11.   
  12.     ngx_queue_t reusable_connections_queue; //再利用连接队列
  13.   
  14.     ngx_array_t listening; //监听数组
  15.     ngx_array_t pathes; //路径数组
  16.     ngx_list_t open_files; //打开文件链表
  17.     ngx_list_t shared_memory; //共享内存链表
  18.   
  19.     ngx_uint_t connection_n; //连接个数
  20.     ngx_uint_t files_n; //打开文件个数
  21.   
  22.     ngx_connection_t *connections; //连接
  23.     ngx_event_t *read_events; //读事件
  24.     ngx_event_t *write_events; //写事件
  25.   
  26.     ngx_cycle_t *old_cycle; //old cycle指针
  27.   
  28.     ngx_str_t conf_file; //配置文件
  29.     ngx_str_t conf_param; //配置参数
  30.     ngx_str_t conf_prefix; //配置前缀
  31.     ngx_str_t prefix; //前缀
  32.     ngx_str_t lock_file; //锁文件
  33.     ngx_str_t hostname; //主机名
  34. }

该结构体的大小是确定的,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队列
  • poolconf_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
    • 关闭多余的打开文件

具体请参考附录代码,不需要细究每一步实现,重要的是要搞清楚其初始化流程。初始化过程中全局结构ngx_cycle结构图如下。

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

点击(此处)折叠或打开

  1. (gdb) p *ngx_cycle
  2. $3 = {
  3.   conf_ctx = 0x6b1060,
  4.   pool = 0x6b0280,
  5.   log = 0x6b02e8,
  6.   new_log = {
  7.     log_level = 4,
  8.     file = 0x6b0558,
  9.     connection = 0,
  10.     handler = 0,
  11.     data = 0x0,
  12.     action = 0x0
  13.   },
  14.   files = 0x0,
  15.   free_connections = 0x0,
  16.   free_connection_n = 0,
  17.   reusable_connections_queue = {
  18.     prev = 0x6b0330,
  19.     next = 0x6b0330
  20.   },
  21.   listening = {
  22.     elts = 0x6b0930,
  23.     nelts = 1,
  24.     size = 184,
  25.     nalloc = 10,
  26.     pool = 0x6b0280
  27.   },
  28.   pathes = {
  29.     elts = 0x6b04d8,
  30.     nelts = 5,
  31.     size = 8,
  32.     nalloc = 10,
  33.     pool = 0x6b0280
  34.   },
  35.   open_files = {
  36.     last = 0x6b0398,
  37.     part = {
  38.       elts = 0x6b0528,
  39.       nelts = 2,
  40.       next = 0x0
  41. ---Type <return> to continue, or q <return> to quit---
  42.     },
  43.     size = 48,
  44.     nalloc = 20,
  45.     pool = 0x6b0280
  46.   },
  47.   shared_memory = {
  48.     last = 0x6b03d0,
  49.     part = {
  50.       elts = 0x6b08e8,
  51.       nelts = 0,
  52.       next = 0x0
  53.     },
  54.     size = 72,
  55.     nalloc = 1,
  56.     pool = 0x6b0280
  57.   },
  58.   connection_n = 1024,
  59.   files_n = 0,
  60.   connections = 0x0,
  61.   read_events = 0x0,
  62.   write_events = 0x0,
  63.   old_cycle = 0x0,
  64.   conf_file = {
  65.     len = 32,
  66.     data = 0x6b04b7 "/usr/local/nginx/conf/nginx.conf"
  67.   },
  68.   conf_param = {
  69.     len = 0,
  70.     data = 0x6b04d8 "\240{l"
  71.   },
  72.   conf_prefix = {
  73.     len = 22,
  74.     data = 0x6b0490 "/usr/local/nginx/conf//usr/local/nginx//usr/local/nginx/conf/nginx.conf"
  75.   },
  76.   prefix = {
  77.     len = 17,
  78.     data = 0x6b04a6 "/usr/local/nginx//usr/local/nginx/conf/nginx.conf"
  79.   },
  80.   lock_file = {
  81. ---Type <return> to continue, or q <return> to quit---
  82.     len = 33,
  83.     data = 0x6ccee0 "/usr/local/nginx/logs/nginx.lock.accept"
  84.   },
  85.   hostname = {
  86.     len = 4,
  87.     data = 0x6b11c0 "yu30"
  88.   }
  89. }

3.注意问题

3.1如何调用CORE模块的callback函数?

即如可调用core模块的create_conf()init_conf()

(1) callback定义

file: ./src/core/ngx_conf_file.h

点击(此处)折叠或打开

  1. typedef struct {                  //定义core模块上下文类型
  2.     ngx_str_t name;               //模块名,即ngx_core_module_ctx结构体对象的ngx_string("core")
  3.     void *(*create_conf)(ngx_cycle_t *cycle);           //创建配置的callback
  4.     char *(*init_conf)(ngx_cycle_t *cycle, void *conf); //初始化配置的callback
  5. } ngx_core_module_t

(2) callback初始化

静态初始化ngx_core_module_ctxngx_core_module结构。在编译期间就已确定CORE模块的callback了。

file: ./src/core/nginx.c

点击(此处)折叠或打开

  1. static ngx_core_module_t ngx_core_module_ctx = { //定义ngx_core_module模块上下文,改方式属于静态初始化
  2.     ngx_string("core"),
  3.     ngx_core_module_create_conf,
  4.     ngx_core_module_init_conf
  5. };
  6.   
  7.   
  8. ngx_module_t ngx_core_module = { //定义ngx_core_module模块,也是静态初始化
  9.     NGX_MODULE_V1,
  10.     &ngx_core_module_ctx, /* module context */
  11.     ngx_core_commands, /* module directives */
  12.     NGX_CORE_MODULE, /* module type */
  13.     NULL, /* init master */
  14.     NULL, /* init module */
  15.     NULL, /* init process */
  16.     NULL, /* init thread */
  17.     NULL, /* exit thread */
  18.     NULL, /* exit process */
  19.     NULL, /* exit master */
  20.     NGX_MODULE_V1_PADDING
  21. }

静态初始化ngx_core_commands结构。

file: ./src/core/nginx.c

点击(此处)折叠或打开

  1. static ngx_command_t ngx_core_commands[] = { //静态初始化core模块的命令
  2.   
  3.     { ngx_string("daemon"),
  4.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  5.       ngx_conf_set_flag_slot,
  6.       0,
  7.       offsetof(ngx_core_conf_t, daemon),
  8.       NULL },
  9.   
  10.     { ngx_string("master_process"),
  11.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  12.       ngx_conf_set_flag_slot,
  13.       0,
  14.       offsetof(ngx_core_conf_t, master),
  15.       NULL },
  16.   
  17.     { ngx_string("timer_resolution"),
  18.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  19.       ngx_conf_set_msec_slot,
  20.       0,
  21.       offsetof(ngx_core_conf_t, timer_resolution),
  22.       NULL },
  23.   
  24.     { ngx_string("pid"),
  25.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  26.       ngx_conf_set_str_slot,
  27.       0,
  28.       offsetof(ngx_core_conf_t, pid),
  29.       NULL },
  30.   
  31.     { ngx_string("lock_file"),
  32.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  33.       ngx_conf_set_str_slot,
  34.       0,
  35.       offsetof(ngx_core_conf_t, lock_file),
  36.       NULL },
  37.   
  38.     { ngx_string("worker_processes"),
  39.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  40.       ngx_conf_set_num_slot,
  41.       0,
  42.       offsetof(ngx_core_conf_t, worker_processes),
  43.       NULL },
  44.   
  45.     /* ... 省略中间的定义 */
  46.   
  47. #if (NGX_THREADS)
  48.   
  49.     { ngx_string("worker_threads"),
  50.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  51.       ngx_conf_set_num_slot,
  52.       0,
  53.       offsetof(ngx_core_conf_t, worker_threads),
  54.       NULL },
  55.   
  56.     { ngx_string("thread_stack_size"),
  57.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  58.       ngx_conf_set_size_slot,
  59.       0,
  60.       offsetof(ngx_core_conf_t, thread_stack_size),
  61.       NULL },
  62.   
  63. #endif
  64.   
  65.       ngx_null_command
  66. }

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()代码

省略,可自行研究。 
阅读(1459) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~