Chinaunix首页 | 论坛 | 博客
  • 博客访问: 380029
  • 博文数量: 56
  • 博客积分: 1449
  • 博客等级: 中尉
  • 技术积分: 822
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-08 10:24
文章分类

全部博文(56)

文章存档

2014年(7)

2012年(13)

2011年(10)

2010年(26)

分类: 服务器与存储

2014-08-11 16:49:20

最近看nginx的代码, 从main主线开始老抓不住主框架代码和各个模块是如何耦合在一起的, 不知道有些东西是在哪儿初始化, 如何运作.
在此稍微记下主框架代码和各个模块的基本交互方式.

首先在nginx.c文件中的main函数

点击(此处)折叠或打开

  1. ngx_max_module = 0;
  2.     for (i = 0; ngx_modules[i]; i++) {
  3.         ngx_modules[i]->index = ngx_max_module++;
  4.     }
ngx_modules包含所有可用的模块指针, 在此为列表中的每个模块分配一个索引, 该索引用来索引模块的配置上下文结构指针在cycle->conf_ctx中的位置.

接下来调用ngx_init_cycle.
ngx_cycle.c文件中ngx_init_cycle函数

点击(此处)折叠或打开

  1. for (i = 0; ngx_modules[i]; i++) {
  2.         if (ngx_modules[i]->type != NGX_CORE_MODULE) {
  3.             continue;
  4.         }

  5.         module = ngx_modules[i]->ctx;

  6.         if (module->create_conf) {
  7.             rv = module->create_conf(cycle);
  8.             if (rv == NULL) {
  9.                 ngx_destroy_pool(pool);
  10.                 return NULL;
  11.             }
  12.             cycle->conf_ctx[ngx_modules[i]->index] = rv;
  13.         }
  14.     }
调用所有核心模块的create_conf方法来创建各个模块的配置上下文结构体并保存在cycle->conf_ctx数组中.

点击(此处)折叠或打开

  1. if (ngx_conf_param(&conf) != NGX_CONF_OK) {
  2.         environ = senv;
  3.         ngx_destroy_cycle_pools(&conf);
  4.         return NULL;
  5.     }
解析命令行中的配置项.

点击(此处)折叠或打开

  1. if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
  2.         environ = senv;
  3.         ngx_destroy_cycle_pools(&conf);
  4.         return NULL;
  5.     }
解析主配置文件. 在解析时, 核心模块会调用其从属模块的创建配置上下文结构体方法以及初始化结构体上下文结构体方法. 例如ngx_events_module.

点击(此处)折叠或打开

  1. static ngx_command_t ngx_events_commands[] = {

  2.     { ngx_string("events"),
  3.       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
  4.       ngx_events_block,
  5.       0,
  6.       0,
  7.       NULL },

  8.       ngx_null_command
  9. };
在配置文件中遇到"event" 这个配置块后. ngx_events_block会被调用.
ngx_event.c文件ngx_events_block函数:

点击(此处)折叠或打开

  1. /* count the number of the event modules and set up their indices */

  2.     ngx_event_max_module = 0;
  3.     for (i = 0; ngx_modules[i]; i++) {
  4.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  5.             continue;
  6.         }

  7.         ngx_modules[i]->ctx_index = ngx_event_max_module++;
  8.     }
为所有属于NGX_EVENT_MODULE的模块分配索引, 其用来索引每个事件模块的配置上下文结构体指针在主事件模块配置上下文指针数组的位置.

点击(此处)折叠或打开

  1. for (i = 0; ngx_modules[i]; i++) {
  2.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  3.             continue;
  4.         }

  5.         m = ngx_modules[i]->ctx;

  6.         if (m->create_conf) {
  7.             (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
  8.             if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
  9.                 return NGX_CONF_ERROR;
  10.             }
  11.         }
  12.     }
调用事件模块的create_conf方法创建每个的配置上下文结构体.
接下来会解析events配置块中的所有配置项.
接着再调用所有事件模块的init_conf方法用默认值来初始化那些在配置文件中没有配置的配置项:

点击(此处)折叠或打开

  1. for (i = 0; ngx_modules[i]; i++) {
  2.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  3.             continue;
  4.         }

  5.         m = ngx_modules[i]->ctx;

  6.         if (m->init_conf) {
  7.             rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]);
  8.             if (rv != NGX_CONF_OK) {
  9.                 return rv;
  10.             }
  11.         }
  12.     }


点击(此处)折叠或打开

  1. for (i = 0; ngx_modules[i]; i++) {
  2.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  3.             continue;
  4.         }

  5.         m = ngx_modules[i]->ctx;

  6.         if (m->init_conf) {
  7.             rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]);
  8.             if (rv != NGX_CONF_OK) {
  9.                 return rv;
  10.             }
  11.         }
  12.     }

接下来轮到核心模块来初始化配置项了:

点击(此处)折叠或打开

  1. for (i = 0; ngx_modules[i]; i++) {
  2.         if (ngx_modules[i]->type != NGX_CORE_MODULE) {
  3.             continue;
  4.         }

  5.         module = ngx_modules[i]->ctx;

  6.         if (module->init_conf) {
  7.             if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
  8.                 == NGX_CONF_ERROR)
  9.             {
  10.                 environ = senv;
  11.                 ngx_destroy_cycle_pools(&conf);
  12.                 return NULL;
  13.             }
  14.         }
  15.     }
到此所有模块的配置环境上下文结构体通过解析配置文件以及预设的初始值已经都初始化好了.

点击(此处)折叠或打开

  1. for (i = 0; ngx_modules[i]; i++) {
  2.         if (ngx_modules[i]->init_module) {
  3.             if (ngx_modules[i]->init_module(cycle) != NGX_OK) {
  4.                 /* fatal */
  5.                 exit(1);
  6.             }
  7.         }
  8.     }
调用*所有*模块的init_module方法来初始化各个模块.  大部分模块都没有提供这个方法.
ngx_init_conf函数结束. 回到main函数.
mian--->ngx_master_process_cycle-->ngx_start_worker_processes-->ngx_spawn_process-->ngx_worker_process_cycle-->ngx_worker_process_init

点击(此处)折叠或打开

  1. for (i = 0; ngx_modules[i]; i++) {
  2.         if (ngx_modules[i]->init_process) {
  3.             if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
  4.                 /* fatal */
  5.                 exit(2);
  6.             }
  7.         }
  8.     }
调用*所有*模块的init_process方法, 可以参考ngx_event_core_module的init_process方法.

以上就是nginx主框架和模块之间的交互. 至于模块nginx这个框架中具体是怎么运转的.  需要
看event模块, nginx使用事件驱动模型. 其他的应用模块都依靠event模块来带动. 待仔细看完代码再
总结.








阅读(2271) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~