nginx源碼學習(二)ngx_init_cycle(&init_cycle)函數解析

1、以下是我閱讀nginx(1.13.2版本)源碼的一些心得,個人覺得學一個東西最好學它的思想,學會舉一反三。因爲互聯網的東西實在太多 了。
上一章我對nginx啓動流程做了一個大概的描述,這一張我詳細進入初始化的核心方法進行探索。文章尾部會附上一張nginx中核心結構體
nginx_cycle_s的圖,方便在閱讀源代碼的時候進行對比和理解。

函數名稱:
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle)

     //第一步:聲明這些變量,變量的意義在初始化的時候進行說明
    void                *rv;
    char               **senv;
    ngx_uint_t           i, n;
    ngx_log_t           *log;
    ngx_time_t          *tp;
    ngx_conf_t           conf;
    ngx_pool_t          *pool;
    ngx_cycle_t         *cycle, **old;
    ngx_shm_zone_t      *shm_zone, *oshm_zone;
    ngx_list_part_t     *part, *opart;
    ngx_open_file_t     *file;
    ngx_listening_t     *ls, *nls;
    ngx_core_conf_t     *ccf, *old_ccf;
    ngx_core_module_t   *module;
    char                 hostname[NGX_MAXHOSTNAMELEN];

//第二步:開始初始化這些變量把指針賦值給cycle結構體
   
    ngx_timezone_update();
    ngx_time_update(); //調用ngx_timezone_update()更新時區,調用ngx_time_update()更新時間
    pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);//申請一個空間內存池,NGX_CYCLE_POOL_SIZE的值爲16*1024
    cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));//從內存池中申請內存存放cycle結構體,這個是核心的結構體
  //這些已經在main函數中獲取到的值直接賦值給新的核心結構體cycle,不需要再次去解析
    cycle->pool = pool;
    cycle->log = log;
    cycle->old_cycle = old_cycle;
    cycle->conf_prefix.len = old_cycle->conf_prefix.len;
    cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);
     cycle->prefix.len = old_cycle->prefix.len;
    cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix);
     cycle->conf_file.len = old_cycle->conf_file.len;
    cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
     cycle->conf_param.len = old_cycle->conf_param.len;
    cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param);
     ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *);//初始化一個大小爲n,可動態擴展的數組,cycle的paths用來存儲的是路徑,比如配置很多配置文件的路徑
     ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t);
     ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel, ngx_str_rbtree_insert_value);//紅黑樹,平衡二叉樹一種,用來坐二分搜索用的
     ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t); //打開文件的list,具體list結構參考:http://blog.csdn.net/chen19870707/article/details/40400719
     ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t);//共享內存的初始化
     ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t);//連接監聽的數組,具體結構附錄圖
     ngx_queue_init(&cycle->reusable_connections_queue);//隊列初始化,這個結構體比較簡單就兩個屬性, prev,next
     cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));//給每個模塊都分配一個配置屬性指針,後面nginx.conf以及其他配置文件中的配置會放到這裏

     
     第三步:for循環初始化核心的module,讀取配置文件,給cycle中已經初始化了的變量進行賦值。
     1、函數名稱:
     
     ngx_int_t  ngx_cycle_modules(ngx_cycle_t *cycle){
       cycle->modules = ngx_pcalloc(cycle->pool, (ngx_max_module + 1)   * sizeof(ngx_module_t *));//申請內存空間,存放module的結構體
       ngx_memcpy(cycle->modules, ngx_modules,  ngx_modules_n * sizeof(ngx_module_t *));//把全局靜態變量的內存信息拷貝過來,這個ngx_modules是在編譯的時候確定好的,即你安裝的時候指定需要使用的擴展,具體可以查看上一章的內容
       cycle->modules_n = ngx_modules_n; //賦值擴展的數量
     }
     2、核心模塊配置信息預處理:
         
 for (i = 0; cycle->modules[i]; i++) {
        if (cycle->modules[i]->type != NGX_CORE_MODULE) {//非核心模塊不處理
            continue;
        }

        module = cycle->modules[i]->ctx; //模塊的上下文

        if (module->create_conf) {
            rv = module->create_conf(cycle);
            if (rv == NULL) {
                ngx_destroy_pool(pool);
                return NULL;
            }
            cycle->conf_ctx[cycle->modules[i]->index] = rv;
        }
    }
    conf.ctx = cycle->conf_ctx;
    conf.cycle = cycle;
    conf.pool = pool;
    conf.log = log;
    conf.module_type = NGX_CORE_MODULE;
    conf.cmd_type = NGX_MAIN_CONF;

     3、準備了這些之後就可以解析配置文件了:
if (ngx_conf_param(&conf) != NGX_CONF_OK) {
    environ = senv;
    ngx_destroy_cycle_pools(&conf);
    return NULL;
}

if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
    environ = senv;
    ngx_destroy_cycle_pools(&conf);
    return NULL;
}
     第一個if解析nginx命令行參數’-g’加入的配置。第二個if解析nginx配置文件。好的設計就體現在接口極度簡化,模塊之間的耦合非常低。這裏只使用區區10行完成了配置的解析。在這裏,我們先淺嘗輒止,具體nginx如何解析配置,我們將在後面的小節做細緻的介紹。-g是指在命令行加入臨時的配置信息,下一章直接解析ngx_conf_parse的詳細實現,分析是如何對配置文件進行解析的。
     
     
     
附圖(從網上找的,自己畫太麻煩):


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章