nginx学習12 ngx_cycle_tとngx_init_cycle


nginxの起動中にngx_init_cycleという関数はほとんどの初期化作業を行い、初期化された変数はngx_に保存されます.cycle_tという構造体では,この関数を深く理解するためにそれらの初期化作業を行い,後で参考にするために時間研究を行い,書いた.
1ngx_cycle_t
この構造体については先に簡単に紹介したが,ここでは後述しない.
2ngx_init_cycle
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle);
まずこのoldを見てみましょうcycleパラメータはどこから来ましたか:
   ngx_cycle_t      *cycle, init_cycle;
    init_cycle.pool = ngx_create_pool(1024, log);//     
    if (init_cycle.pool == NULL) {
        return 1;
    }

    ......
    ......

    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }
	
    cycle = ngx_init_cycle(&init_cycle);

呼び出しngx_が表示されますint_cycleの前に、このold_cycleにはprefix,conf_などのパラメータが保存されています.prefix,conf_file, conf_para.主にngx_process_optionsという関数でold_を初期化cycle、この関数は簡単です.コードを見てください.
static ngx_int_t
ngx_process_options(ngx_cycle_t *cycle)
{
    u_char  *p;
    size_t   len;

    if (ngx_prefix) {
        len = ngx_strlen(ngx_prefix);
        p = ngx_prefix;

        if (!ngx_path_separator(*p)) {
            p = ngx_pnalloc(cycle->pool, len + 1);
            if (p == NULL) {
                return NGX_ERROR;
            }

            ngx_memcpy(p, ngx_prefix, len);
            p[len++] = '/';
        }

        cycle->conf_prefix.len = len;
        cycle->conf_prefix.data = p;
        cycle->prefix.len = len;
        cycle->prefix.data = p;

    } else {

#ifndef NGX_PREFIX

        p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
        if (p == NULL) {
            return NGX_ERROR;
        }

        if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {//         
            ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
            return NGX_ERROR;
        }

        len = ngx_strlen(p);

        p[len++] = '/';

        cycle->conf_prefix.len = len;
        cycle->conf_prefix.data = p;//    
        cycle->prefix.len = len;
        cycle->prefix.data = p;//    

#else

#ifdef NGX_CONF_PREFIX
        ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);//            
#else
        ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
#endif
        ngx_str_set(&cycle->prefix, NGX_PREFIX);

#endif
    }

    if (ngx_conf_file) {
        cycle->conf_file.len = ngx_strlen(ngx_conf_file);
        cycle->conf_file.data = ngx_conf_file;

    } else {
        ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
    }

    if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
        return NGX_ERROR;
    }

    for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
         p > cycle->conf_file.data;
         p--)
    {
        if (ngx_path_separator(*p)) {
            cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
            cycle->conf_prefix.data = ngx_cycle->conf_file.data;
            break;
        }
    }

    if (ngx_conf_params) {
        cycle->conf_param.len = ngx_strlen(ngx_conf_params);
        cycle->conf_param.data = ngx_conf_params;
    }

    if (ngx_test_config) {
        cycle->log->log_level = NGX_LOG_INFO;
    }

    return NGX_OK;
}

これからキー:ngx_init_cycle、実行手順に従って
2.1 ngx_を呼び出すtimezone_update()、ngx_timeofday() 、ngx_time_update(0,0)時間キャリブレーションを行う
 ngx_timezone_update();

    /* force localtime update with a new timezone */

    tp = ngx_timeofday();
    tp->sec = 0;

    ngx_time_update();

2.2新しいngx_を作成するcycle_t変数cycleは、そのほとんどのメンバーフィールドを初期化し、いくつかは入力されたold_からcycleは直接コピーしました.これらのフィールドには、log、conf_が含まれています.prefix,prefix,conf_file,conf_param,pathes配列の初期化,openの初期化filesチェーンテーブル、初期化shared_memoryチェーンテーブル、listening配列の初期化など.
    cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));//     cycle,    cycle     
    if (cycle == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    cycle->pool = pool;//  cycle    
    cycle->log = log;//  log
    cycle->new_log.log_level = NGX_LOG_ERR;
    cycle->old_cycle = old_cycle;//old_cycle

    cycle->conf_prefix.len = old_cycle->conf_prefix.len;// nginx.c ngx_process_options   
    cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix);
    if (cycle->conf_prefix.data == NULL) {//       NULL
        ngx_destroy_pool(pool);
        return NULL;
    }

    cycle->prefix.len = old_cycle->prefix.len;// nginx.c ngx_process_options   
    cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix);
    if (cycle->prefix.data == NULL) {//     NULL
        ngx_destroy_pool(pool);
        return NULL;
    }

    cycle->conf_file.len = old_cycle->conf_file.len;
    cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
    if (cycle->conf_file.data == NULL) {//               NULL
        ngx_destroy_pool(pool);
        return NULL;
    }
    ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data,
                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);
    if (cycle->conf_param.data == NULL) {//    
        ngx_destroy_pool(pool);
        return NULL;
    }


    n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;//Nginx       

    cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));//      
    if (cycle->pathes.elts == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    cycle->pathes.nelts = 0;
    cycle->pathes.size = sizeof(ngx_path_t *);
    cycle->pathes.nalloc = n;
    cycle->pathes.pool = pool;

	/*  open_files   */
    if (old_cycle->open_files.part.nelts) {
        n = old_cycle->open_files.part.nelts;
        for (part = old_cycle->open_files.part.next; part; part = part->next) {
            n += part->nelts;
        }

    } else {
        n = 20;
    }
	//   open_files  ,
    if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
        != NGX_OK)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

	/*  old_cycle shared_memory       cycle    */
    if (old_cycle->shared_memory.part.nelts) {
        n = old_cycle->shared_memory.part.nelts;
        for (part = old_cycle->shared_memory.part.next; part; part = part->next)
        {
            n += part->nelts;
        }

    } else {
        n = 1;
    }
	//ngx_list_init        elts,       
    if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
        != NGX_OK)
    {
        ngx_destroy_pool(pool);
        return NULL;
    }

    n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;//  listening    10
	/*   listening  */
    cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
    if (cycle->listening.elts == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    cycle->listening.nelts = 0;
    cycle->listening.size = sizeof(ngx_listening_t);
    cycle->listening.nalloc = n;
    cycle->listening.pool = pool;

	//       ,            ngx_connection_t
    ngx_queue_init(&cycle->reusable_connections_queue);

	//   conf_ctx,ngx_max_module nginx      
    cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
    if (cycle->conf_ctx == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }


    if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed");
        ngx_destroy_pool(pool);
        return NULL;
    }

    /* on Linux gethostname() silently truncates name that does not fit */
	//   hostname
    hostname[NGX_MAXHOSTNAMELEN - 1] = '\0';
    cycle->hostname.len = ngx_strlen(hostname);

    cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len);
    if (cycle->hostname.data == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }
	//        
    ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);

2.3すべてのNGX_を呼び出すCORE_MODULEのcreate_confは構成構造体を構築しconf_に保存するctx配列の中
for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = ngx_modules[i]->ctx;

        if (module->create_conf) {
            rv = module->create_conf(cycle);
            if (rv == NULL) {
                ngx_destroy_pool(pool);
                return NULL;
            }
			//           conf_ctx   ,     ngx_module_t.index
            cycle->conf_ctx[ngx_modules[i]->index] = rv;
        }
    }


    senv = environ;

	/*       ngx_conf_t conf*/
    ngx_memzero(&conf, sizeof(ngx_conf_t));
    /* STUB: init array ? */
    conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
    if (conf.args == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }

    conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
    if (conf.temp_pool == NULL) {
        ngx_destroy_pool(pool);
        return NULL;
    }


    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;//

2.4コマンドラインとプロファイルからすべての構成をcycleのconf_に更新するctx中:ngx_を最初に呼び出すconf_paramは、コマンドラインのコマンド(-g directives)をコンフィギュレーション構造に変換するcycle.conf_ctxにポインタを入れ、ngx_conf_parse(.,filename)を呼び出してコンフィギュレーション構造に変換するポインタをcycleに加える.conf_ctxで.
if (ngx_conf_param(&conf) != NGX_CONF_OK) {//src/core/ngx_conf_file.c
        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 (ngx_test_config && !ngx_quiet_mode) {
        ngx_log_stderr(0, "the configuration file %s syntax is ok",
                       cycle->conf_file.data);
    }

2.5すべてのコアモジュールのinit関数を呼び出し、すべてのコアモジュールの構成構造体を初期化する
 for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->type != NGX_CORE_MODULE) {
            continue;
        }

        module = ngx_modules[i]->ctx;

        if (module->init_conf) {//     init_conf               
            if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index])
                == NGX_CONF_ERROR)
            {
                environ = senv;
                ngx_destroy_cycle_pools(&conf);
                return NULL;
            }
        }
    }

    if (ngx_process == NGX_PROCESS_SIGNALLER) {
        return cycle;
    }

2.6コアモジュールngx_を取得core_doduleの構成構造を呼び出し、ngx_を呼び出します.create_pidfile pidファイルの作成
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (ngx_test_config) {
		//    pid  
        if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {
            goto failed;
        }

    } else if (!ngx_is_init_cycle(old_cycle)) {

        /*
         * we do not create the pid file in the first ngx_init_cycle() call
         * because we need to write the demonized process pid
         */
		//  old_ccf     
        old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,
                                                   ngx_core_module);
        if (ccf->pid.len != old_ccf->pid.len
            || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0)
        {
            /* new pid file name */

            if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {
                goto failed;
            }

            ngx_delete_pidfile(old_cycle);
        }
    }

2.7 ngx_を呼び出すtest_lockfile(filename,log),ngx_create_pathes(cycle,user)は、errorlogファイルを開き、cycle->new_に値を割り当てます.log.file
 if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) {
        goto failed;
    }

    if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) {
        goto failed;
    }


    if (cycle->new_log.file == NULL) {
        cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);
        if (cycle->new_log.file == NULL) {
            goto failed;
        }
    }

2.8新しいファイルを開き、手順2でcycle->open_について説明するfilesというチェーンテーブルは空ですが、予めスペースを割り当ててあるだけで、データはありません.ここでファイルが開く可能性があるのは、前にプロファイルを読むときに、各フックを呼び出す過程で、このチェーンテーブルを埋めて、ngx_open_file_t構造変数が埋め込まれ(構造体にファイルを開くパス情報が含まれている)、cycleのメンバーを変更します:cycle->log=&cycle->new_log;pool->log=&cycle->new_log;
2.9共有メモリとopen_の作成files同様、ステップ2でcycle->share_memoryも空のチェーンテーブルに初期化され、空間が予め割り当てられている場合、チェーンテーブルにngx_が埋め込まれている場合shm_zone_t構造変数(共有メモリが必要なサイズやIDなどの情報が含まれている)では、ここで共有メモリが割り当てられ、適切な初期化フックが呼び出されて割り当てられた共有メモリが初期化され、各共有メモリにはname識別子が表示され、ここでもいくつかの並べ替えが行われ、すでに割り当てられているものは割り当てられず、open_filesやshare_memoryの処理過程からnginxリソース管理では集中的に割り当てられ、リソースを要求するときに説明的な構造変数を割り当て、適切なタイミングでリソースを本当に割り当てます.
2.10 listening socketsを処理し、cycle->listeningはngx_listening_t構造の配列、cycle->listeningをold_にcycle->listening比較し、cycle->listeningのステータス情報を設定し、ngx_を呼び出します.open_listening_sockets(cycle)はcycle->listeningのすべてのリスニングsocketを起動し、socket,bindをループ呼び出し、listenはサービス側リスニングsocketの起動を完了する.次にngx_を呼び出すconfigure_listening_sockets(cycle)は、ngx_に基づいてリスニングsocketを構成します.listening_t中の状態情報socketの読み書きキャッシュとTCP_を設定するDEFER_ACCEPT.
if (old_cycle->listening.nelts) {//  old_cycle         
        ls = old_cycle->listening.elts;
        for (i = 0; i < old_cycle->listening.nelts; i++) {
            ls[i].remain = 0;//             
        }

        nls = cycle->listening.elts;
        for (n = 0; n < cycle->listening.nelts; n++) {

            for (i = 0; i < old_cycle->listening.nelts; i++) {
                if (ls[i].ignore) {//    1      ngx_lisenting_t     ,
                    continue;	   // 0          
                }
/********************************************************************************************************/
				//    :nls[n].sockaddr         
/********************************************************************************************************/
                if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK)
                {
                    nls[n].fd = ls[i].fd;
                    nls[n].previous = &ls[i];
                    ls[i].remain = 1;//           

                    if (ls[n].backlog != nls[i].backlog) {
                        nls[n].listen = 1;//      
                    }

#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)

                    /*
                     * FreeBSD, except the most recent versions,
                     * could not remove accept filter
                     */
                    nls[n].deferred_accept = ls[i].deferred_accept;

                    if (ls[i].accept_filter && nls[n].accept_filter) {
                        if (ngx_strcmp(ls[i].accept_filter,
                                       nls[n].accept_filter)
                            != 0)
                        {
                            nls[n].delete_deferred = 1;
                            nls[n].add_deferred = 1;
                        }

                    } else if (ls[i].accept_filter) {
                        nls[n].delete_deferred = 1;

                    } else if (nls[n].accept_filter) {
                        nls[n].add_deferred = 1;
                    }
#endif

#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)

                    if (ls[n].deferred_accept && !nls[n].deferred_accept) {
                        nls[n].delete_deferred = 1;

                    } else if (ls[i].deferred_accept != nls[n].deferred_accept)
                    {
                        nls[n].add_deferred = 1;
                    }
#endif
                    break;
                }
            }

            if (nls[n].fd == -1) {
                nls[n].open = 1;
            }
        }

    } else {
        ls = cycle->listening.elts;
        for (i = 0; i < cycle->listening.nelts; i++) {
            ls[i].open = 1;
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
            if (ls[i].accept_filter) {
                ls[i].add_deferred = 1;
            }
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
            if (ls[i].deferred_accept) {
                ls[i].add_deferred = 1;
            }
#endif
        }
    }
	/*
	      :cycle->listening      ngx_listening_t sockaddr       
	  ngx_open_listening_sockets                
	*/
	//  cycle->listening      socket,    socket,bind,listen       socket   
    if (ngx_open_listening_sockets(cycle) != NGX_OK) {
        goto failed;
    }

    if (!ngx_test_config) {//    ngx_configure_listening_sockets(cycle)    socket
        ngx_configure_listening_sockets(cycle);
この段階でまだ問題が解決されていません(注釈を参照)???
2.11すべてのモジュールのinit_を呼び出すmoduleメソッド、ngx_のみevent_core_module定義init_module.
for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->init_module) {
            if (ngx_modules[i]->init_module(cycle) != NGX_OK) {
                /* fatal */
                exit(1);
            }
        }
    }

2.12 oldに残っているものを閉じるか削除します.cycleのリソースは、まず不要な共有メモリを解放し、次に使用しないリスニングsocketを閉じ、使用しないオープンファイルを閉じ、最後にold_cycleをngx_に入れるold_cyclesではngx_ですcycle_t*の配列、最後にタイマーを設定し、定期的にngx_をコールバックします.cleaner_eventクリーンアップngx_old_cycles、ここでは30000 msのクリーンアップを設定しています.
 if (ngx_temp_pool == NULL) {
        ngx_temp_pool = ngx_create_pool(128, cycle->log);
        if (ngx_temp_pool == NULL) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                          "could not create ngx_temp_pool");
            exit(1);
        }

        n = 10;
        ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,
                                          n * sizeof(ngx_cycle_t *));
        if (ngx_old_cycles.elts == NULL) {
            exit(1);
        }
        ngx_old_cycles.nelts = 0;
        ngx_old_cycles.size = sizeof(ngx_cycle_t *);
        ngx_old_cycles.nalloc = n;
        ngx_old_cycles.pool = ngx_temp_pool;
		//   ngx_cleaner_event  
        ngx_cleaner_event.handler = ngx_clean_old_cycles;//    handler
        ngx_cleaner_event.log = cycle->log;
        ngx_cleaner_event.data = &dumb;
        dumb.fd = (ngx_socket_t) -1;
    }

    ngx_temp_pool->log = cycle->log;

    old = ngx_array_push(&ngx_old_cycles);
    if (old == NULL) {
        exit(1);
    }
    *old = old_cycle;
	// ngx_cleaner_event        ,    old_cycle
    if (!ngx_cleaner_event.timer_set) {
        ngx_add_timer(&ngx_cleaner_event, 30000);//30000  
        ngx_cleaner_event.timer_set = 1;
    }

http://blog.csdn.net/xiaoliangsky/article/details/39996563
次に図を添付します.
画像のソースhttp://blog.csdn.net/lengzijian/article/details/7575813#plain
参考資料:
http://blog.csdn.net/lengzijian/article/details/7575813#plain