Chinaunix首页 | 论坛 | 博客
  • 博客访问: 155359
  • 博文数量: 22
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 350
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-15 09:43
个人简介

专注服务器设计、开发; https://github.com/justscu;

文章分类

全部博文(22)

文章存档

2014年(10)

2013年(2)

2012年(10)

分类: 服务器与存储

2014-04-21 14:18:29

        Nginx的代码结构相对来说,还是非常清晰明了的,共包含有core/event/http/mail四个模块。

1. 模块结构


   1. nginx包含core/event/http/mail四个核心模块。除了这四个核心模块,nginx还可以包含很多子模块,这些模块,可以在编译的时候进行选择。利用./configure --help命令,可以查看包含的子模块,如--with-XXX-module。
    用configure配置后,会生成一个objs/目录,有个ngx_modules.c文件里面声明了所包含的模块ngx_module_t *ngx_modules[]。
    2. 模块的组织(以core模块为例)
    模块包含以下三个重要的数据结构:(1)模块的声明ngx_module_t  ngx_core_module;(2)模块上下文ngx_core_module_t  ngx_core_module_ctx;(3)模块支持的命令ngx_command_t  ngx_core_commands[]
    ngx_module_t中有几个参数值得注意:(1)ngx_command_t* commands,该模块支持的命令;(2)ngx_uint_t type,该模块所属的类型NGX_CORE_MODULE/NGX_EVENT_MODULE/NGX_HTTP_MODULE/NGX_MAIL_MODULE等;(3)void* ctx,模块的上下文,用来存放ngx_core_module_t结构的地址。由于所有的模块的ctx,都存放在一个大的结构ngx_cycle_t中,如何找到每个模块的ctx呢?那就是ngx_uint_t index和ngx_uint_t ctx_index共同定位。在main()函数的代码中,有这样一段:
    ngx_max_module = 0;//从0开始计数
    for (i = 0; ngx_modules[i]; i++) { //遍历各模块
        ngx_modules[i]->index = ngx_max_module++; // 给不同的模块编号
    }
    ... ... 
    for (i = 0; ngx_modules[i]; i++)
    {
        if ( ngx_modules[i]->type != NGX_CORE_MODULE ) // 对NGX_CORE_MODULE模块计数
        {
            continue;
        }
        module = ngx_modules[i]->ctx;//根据ctx找到NGX_CORE_MODULE的上下文结构
        if ( module->create_conf )
        {
                rv = module->create_conf(cycle); //调用回调函数ngx_core_module_create_conf
                if ( rv == NULL )
                {
                        ngx_destroy_pool(pool);
                        return NULL;
                }
                cycle->conf_ctx[ngx_modules[i]->index] = rv;//加入到cycle结构中
        }
    }

    3. core模块的上下文结构,解析配置文件,构造配置文件,初始化配置文件的时候,会调用其回调函数。
    typedef struct {
        ngx_str_t             name; //名字
        void               *(*create_conf)(ngx_cycle_t *cycle);// 构造配置时调用
        char               *(*init_conf)(ngx_cycle_t *cycle, void *conf);//初始化配置时调用
    } ngx_core_module_t;
    struct ngx_command_s {
        ngx_str_t             name; // 指令的名字
        ngx_uint_t            type; // 指令所在模块的类别
        // 从配置文件中,把指令的参数@cf,转换为合适的类型,保存在 @conf中
        char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
        ngx_uint_t            conf; // 指针的偏移,用于 @set 函数 ; 指令解析后的存放位置
        ngx_uint_t            offset; //
        void                 *post;
    };

2. main函数分析

 点击(此处)折叠或打开

  1. int main(int argc, char *const *argv)
  2. {
  3.     ngx_int_t i;
  4.     ngx_log_t *log;
  5.     ngx_cycle_t *cycle, init_cycle;
  6.     ngx_core_conf_t *ccf;
  7. // 初始化错误信息,并放入到全局变量 ngx_sys_errlist 中
  8.     if (ngx_strerror_init() != NGX_OK) {
  9.         return 1;
  10.     }
  11. // 获取启动参数
  12.     if (ngx_get_options(argc, argv) != NGX_OK) {
  13.         return 1;
  14.     }
  15. //"-v" 参数启动,进程测试
  16.     if (ngx_show_version) {
  17.         ... ...
  18.     }
  19. // 初始化,并更新时间数组
  20.     ngx_time_init();
  21. // 获取本进程ID
  22.     ngx_pid = ngx_getpid();
  23. // 初始化并打开log文件
  24.     log = ngx_log_init(ngx_prefix);
  25.     if (log == NULL) {
  26.         return 1;
  27.     }

  28.     /*
  29.      * init_cycle->log is required for signal handlers and
  30.      * ngx_process_options()
  31.      */
  32.     ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
  33.     init_cycle.log = log;
  34.     ngx_cycle = &init_cycle;
  35.     // 为ngx_cycle_t结构,分配1024的内存
  36.     init_cycle.pool = ngx_create_pool(1024, log);
  37.     if (init_cycle.pool == NULL) {
  38.         return 1;
  39.     }
  40. // 保存启动参数到全局变量 ngx_argv, ngx_argc中
  41.     if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
  42.         return 1;
  43.     }

  44.     if (ngx_process_options(&init_cycle) != NGX_OK) {
  45.         return 1;
  46.     }
  47. // 操作系统参数 初始化
  48.     if (ngx_os_init(log) != NGX_OK) {
  49.         return 1;
  50.     }

  51.     /*
  52.      * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
  53.      */
  54.     // CRC 表
  55.     if (ngx_crc32_table_init() != NGX_OK) {
  56.         return 1;
  57.     }

  58.     if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
  59.         return 1;
  60.     }
  61.     // 启动的时候,给不同的模块,编号码
  62.     ngx_max_module = 0;
  63.     for (i = 0; ngx_modules[i]; i++) {
  64.         ngx_modules[i]->index = ngx_max_module++; // 给不同的模块编号
  65.     }
  66. // 初始化cycle结构
  67.     cycle = ngx_init_cycle(&init_cycle);
  68.     if (cycle == NULL) {
  69.         if (ngx_test_config) {
  70.             ngx_log_stderr(0, "configuration file %s test failed", init_cycle.conf_file.data);
  71.         }
  72.         return 1;
  73.     }

  74.     if (ngx_test_config) {
  75.         if (!ngx_quiet_mode) {
  76.             ngx_log_stderr(0, "configuration file %s test is successful", cycle->conf_file.data);
  77.         }
  78.         return 0;
  79.     }
  80. // 若是"-s XX"参数启动的,进入信号处理函数
  81.     if (ngx_signal) {
  82.         return ngx_signal_process(cycle, ngx_signal);
  83.     }
  84.     ngx_os_status(cycle->log);
  85.     ngx_cycle = cycle;
  86. // 获取core模块的上下文,即配置信息
  87.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  88.     if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
  89.         ngx_process = NGX_PROCESS_MASTER;
  90.     }

  91. // 加入信号处理
  92.     if (ngx_init_signals(cycle->log) != NGX_OK) {
  93.         return 1;
  94.     }
  95. // 后台运行
  96.     if (!ngx_inherited && ccf->daemon) {
  97.         if (ngx_daemon(cycle->log) != NGX_OK) {
  98.             return 1;
  99.         }

  100.         ngx_daemonized = 1;
  101.     }

  102.     if (ngx_inherited) {
  103.         ngx_daemonized = 1;
  104.     }

  105. // 构造pid文件,里面写的是本进程的进程ID
  106.     if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
  107.         return 1;
  108.     }

  109.     if (cycle->log->file->fd != ngx_stderr) {
  110.         if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
  111.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_set_stderr_n " failed");
  112.             return 1;
  113.         }
  114.     }

  115.     if (log->file->fd != ngx_stderr) {
  116.         if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
  117.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_close_file_n " built-in log failed");
  118.         }
  119.     }

  120.     cycle->log->file->fd = 1;
  121.     log->file->fd = 2;
  122.     ngx_use_stderr = 0;

  123.     if (ngx_process == NGX_PROCESS_SINGLE) {
  124.         ngx_single_process_cycle(cycle); // 单进程启动
  125.     } else {
  126.         ngx_master_process_cycle(cycle); // 多进程启动
  127.     }

  128.     return 0;
  129. }


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