天天看點

讀nginx main函數【總綱】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

step 1

ngx_debug_init(); //linux下為空函數

step 2

if (ngx_strerror_init() != NGX_OK) {

    return 1; }

NGX_SYS_NERR,定義在/home/nginx-1.4.4/objs/ngx_auto_config.h, configure的時候自動生成,生成的辦法待研究

debian下的大小為:

讀nginx main函數【總綱】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

static ngx_str_t  *ngx_sys_errlist;//指向一個NGX_SYS_NERR * sizeof(ngx_str_t);大小的記憶體

//周遊NGX_SYS_NERR這麼多個err     for (err = 0; err < NGX_SYS_NERR; err++) {

        msg = strerror(err);   //strerror()用來翻譯錯誤碼的宏定義的意思

        len = ngx_strlen(msg);

        p = malloc(len);

        if (p == NULL) {

            goto failed;

        }

        ngx_memcpy(p, msg, len); //開一塊記憶體,将錯誤碼對應的意思拷貝進去 //将以錯誤碼為下标的元素指派,之後通過錯誤碼可以直接和錯誤意思對應

        ngx_sys_errlist[err].len = len;

        ngx_sys_errlist[err].data = p;

    }

step 3

    if (ngx_get_options(argc, argv) != NGX_OK) {

        return 1;

    }

初始化各環境變量(全局變量)

step 4

ngx_time_init();

伺服器時間的初始化,不明覺厲,需要看到後面再回來研究。

step 5

#if (NGX_PCRE)

    ngx_regex_init();

#endif

正則初始化, 不明覺厲,需要看到後面再回來研究。

step 6

ngx_pid = ngx_getpid();

取得目前程序的程序pid

step 7

    log = ngx_log_init(ngx_prefix);

    if (log == NULL) {

        return 1;

    }

日志初始化,日志子產品後面會單獨開辟一章來分析,先留白。

step 8

#if (NGX_OPENSSL)

    ngx_ssl_init(log);

#endif

SSL初始化

step 9

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));

    init_cycle.log = log;

    ngx_cycle = &init_cycle;

    init_cycle.pool = ngx_create_pool(1024, log);

    if (init_cycle.pool == NULL) {

        return 1;

    }

初始化一個類型為ngx_cycle_t的局部變量,初始化該結構的log指針,pool指針

step 10

    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {

        return 1;

    }

把main函數的argc, argv存在ngx_os_argv、ngx_argc、ngx_argv這三個全局變量裡面, 不明覺厲,日後再說。

step 11

    if (ngx_process_options(&init_cycle) != NGX_OK) {

        return 1;

    }

初始化 ngx_cycle結構體 的 prefix, conf_prefix, conf_file, conf_param 等字段

初始化這些結構體變量是根據ngx_prefix、ngx_conf_file、ngx_conf_params等全局變量來的,而這些全局變量是在ngx_get_options()函數中進行的初始化。

  1. static u_char      *ngx_prefix;         
  2. static u_char      *ngx_conf_file;      
  3. static u_char      *ngx_conf_params;    
讀nginx main函數【總綱】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22
讀nginx main函數【總綱】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

step 12

    if (ngx_os_init(log) != NGX_OK) {

        return 1;

    }

初始化系統相關變量,如記憶體頁面大小 ngx_pagesize , ngx_cacheline_size , 最大連接配接數 ngx_max_sockets 等;

ngx_int_t
ngx_os_init(ngx_log_t *log)
{
    ngx_uint_t  n;

#if (NGX_HAVE_OS_SPECIFIC_INIT)
    if (ngx_os_specific_init(log) != NGX_OK) {
        return NGX_ERROR;
    }
#endif

    ngx_init_setproctitle(log);

	//傳回一分頁的大小, 機關為位元組(byte). 此為系統的分頁大小, 不一定會和硬體分頁大小相同.
	//在intel x86上為4096 bytes
    ngx_pagesize = getpagesize();

	//設定cpu cacheline大小,該宏定義在./ngx_auto_config.h:#define NGX_CPU_CACHE_LINE  32
	//http://blog.csdn.net/zdl1016/article/details/8882092
    ngx_cacheline_size = NGX_CPU_CACHE_LINE;

	//每次循環,n折半
    for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }

#if (NGX_HAVE_SC_NPROCESSORS_ONLN)
    if (ngx_ncpu == 0) {
        ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    }
#endif

    if (ngx_ncpu < 1) {
        ngx_ncpu = 1;
    }

	//不明覺厲,根據CPU類型設定ngx_cacheline_size的大小
    ngx_cpuinfo();

	//RLIMIT_NOFILE參數,擷取程序可以打開的最多檔案數,APUE II P164.之7.11節
    if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
        ngx_log_error(NGX_LOG_ALERT, log, errno,
                      "getrlimit(RLIMIT_NOFILE) failed)");
        return NGX_ERROR;
    }

	//記錄能打開的最大檔案數到ngx_max_sockets全局變量
    ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur;

#if (NGX_HAVE_INHERITED_NONBLOCK || NGX_HAVE_ACCEPT4)
    ngx_inherited_nonblocking = 1;
#else
    ngx_inherited_nonblocking = 0;
#endif

	//設定random函數的種子
    srandom(ngx_time());

    return NGX_OK;
}
           

btw: 關于系統軟限制和硬限制的檢視方式如下

讀nginx main函數【總綱】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

step 13

    if (ngx_crc32_table_init() != NGX_OK) {

        return 1;

    }

不明覺厲,需要專門分析。

step 14

    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {

        return 1;

    }

不明覺厲,需要專門分析。

step 15

    ngx_max_module = 0;

    for (i = 0; ngx_modules[i]; i++) {

        ngx_modules[i]->index = ngx_max_module++;

    }

初始化每個 module 的 index ,并計算module的最大值 ngx_max_module

step 16

    cycle = ngx_init_cycle(&init_cycle);

    if (cycle == NULL) {

        if (ngx_test_config) {

            ngx_log_stderr(0, "configuration file %s test failed",

                           init_cycle.conf_file.data);

        }

        return 1;

    }

對 ngx_cycle 結構進行初始化, 重要,需要細看。

step 17

    if (ngx_signal) {

        return ngx_signal_process(cycle, ngx_signal);

    }

若有信号,則處理信号。

step 18

    ngx_cycle = cycle;

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {

        ngx_process = NGX_PROCESS_MASTER;

    }

step 19

    if (ngx_init_signals(cycle->log) != NGX_OK) {

        return 1;

    }

該函數根據signals來初始化信号。

signals[ ]的定義在src/os/unix/ngx_process.c中,定義了各種信号的處理函數。

step 20

    if (!ngx_inherited && ccf->daemon) {

        if (ngx_daemon(cycle->log) != NGX_OK) {

            return 1;

        }

        ngx_daemonized = 1;

    }

    if (ngx_inherited) {

        ngx_daemonized = 1;

    }

沒看懂,待分析

step 21

    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {

        return 1;

    }

建立程序記錄檔案

step 22

    if (ngx_process == NGX_PROCESS_SINGLE) {

        ngx_single_process_cycle(cycle);

    } else {

        ngx_master_process_cycle(cycle);

    }

進入程序主循環;

  • 若為NGX_PROCESS_SINGLE=1模式,則調用ngx_single_process_cycle()進入程序循環;
  • 否則為master-worker模式,調用ngx_master_process_cycle()進入程序循環;

繼續閱讀