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

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

2015-12-01 19:51 567 查看
链接: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文件中定义,如下。

[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和配置文件解析等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nginx