1.簡介:linux
這篇文章確定是未完待續的...由於做者自己也是剛開始看nginx,只能逐步更新了...若是有錯誤的地方還望諸君海涵並指出。講解的內容主要是按順序在main函數中調用的其餘函數或者宏的做用,其中定義的一些變量不會贅述,但會提到...另外每次介紹函數我都會在代碼段中添加註釋,主要是這個函數所在的文件什麼的,還有就是我會先介紹該函數大體幹了啥,至於函數中執行的過程由於有些太長了,建議最好本身去看一下,錯誤處理方面也會偶爾提到另外個人系統是ubuntu19.04,之因此在這裏特別說明,是由於nginx在不一樣平臺上,對某些路徑字符串什麼的處理有所不一樣,所以本文僅按照我我的的系統上的介紹,可是若是遇到這種狀況我會特別說明。nginx
2.主要內容:ubuntu
ngx_debug_init();
這句宏應該是用做debug的...不知道有沒有啥其餘做用,可是由於nginx裏面名字特別清楚,因此暫時認定這個是用做debug,另外後續可能存在一些我查找不到的宏定義我直接按照nginx名字含義來解釋...若是有新的瞭解再進行更新。數組
if (ngx_strerror_init() != NGX_OK) {//<ngx_errno.c> return 1; }
該函數主要是初始化靜態指針ngx_sys_errlist,將其做爲一個數組首地址利用malloc申請大小爲NGX_SYS_NERR * sizeof(ngx_str_t)的內存,存儲錯誤列表,nginx檢測的錯誤都在這了。socket
(實際上還不就是內核給的errno嘛而後轉換成字符串嘛,搞得巨麻煩)ide
if (ngx_get_options(argc, argv) != NGX_OK) {//<nginx.c> return 1; }
該函數主要是在將nginx啓動的時候傳遞的那些參數選項存儲在nginx.c文件中的全局變量中,以方便以後cycle對象的初始化。(這個沒得吐槽的,由於咱還不瞭解cycle是幹啥用的--初步估計是一個全局的配置結構,稀奇古怪的東西巨多)函數
上圖中的參數後爲若是指明瞭該參數,進行設置的一些靜態變量,這裏-s我有一個參數沒列出來即ngx_process,若是獲得的ngx_sinal在["stop","quit","reopen","reload"]中,那麼ngx_process將被設置爲NGX_PROCESS_SIGNALLER,不然將會記錄一個錯誤,也就是說給定的ngx_sinal只能是此列表中任何一個。測試
if (ngx_show_version) { ngx_show_version_info();//<nginx.c> if (!ngx_test_config) { return 0; } }
根據ngx_get_options()所得的ngx_show_version展現當前nginx版本信息,若是設置了ngx_show_help還會輸出一系列的參數選項,要注意的是輸出傳輸的文件描述符是STDERR_FILENO。ui
ngx_time_init();//<ngx_times.c>
根據當前時間初始化全部須要初始的時間,須要注意的是時間格式存在不一樣。spa
log = ngx_log_init(ngx_prefix);//<ngx_log.c>
先說明下這個返回值,若是初始化log成功,則返回的其實是ngx_log.c文件中的static ngx_log_t ngx_log的地址。另外說明下ngx_refix的做用,它是由ngx_get_options()所獲得的,當NGX_ERROR_LOG_PATH定義了(實際上在個人vscode中找不到這個宏定義),當這個宏定義的字符串長度爲0時(注意是長度不是所佔的內存大小),此函數返回的ngx_log中的字段ngx_log_file的文件描述符就是STDERR_FILENO,不然若是長度不爲0,而且這個宏定義對應的路徑並非一個絕對路徑(即首字符不爲'/'),那麼咱們就須要利用上面所提到的ngx_prefix參數了,nginx的處理方式是將ngx_prefix做爲一個路徑的前綴,並將NGX_ERROR_LOG_PATH加入到ngx_prefix以後,例如:假設ngx_prefix指向的是"/home/zhuiyi",NGX_ERROR_LOG_PATH宏爲"error/errlog.txt",那麼這個路徑實際上會被拼接爲"/home/zhuiyi/error/errlog.txt",以O_WRONLY|O_APPEND|O_CREAT模式打開,權限爲0644,,而後把上述的ngx_log_file文件描述符賦值爲open函數返回的fd。另外這個返回值實際上後來init_cycle->log和它的指向相同。
init_cycle.pool = ngx_create_pool(1024, log);
在nginx官網中的Development guide文檔中有介紹過這個init_cycle,它實際上就是在初始化過程當中起到了初步的一些做用,例如利用上面的pool來分配內存,初始化後續cycle的配置文件的前綴字符串(以此爲一個所謂的base目錄)。如前述提到的,ngx_create_pool()函數是用於create一個內存分配池的,init_cycle將會使用這個內存分配池,對後續的一些須要分配內存的地方進行分配,其size即爲1024。
if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; }
這個函數做用很明顯即複製main函數中的參數(利用ngx_argc,ngx_argv),而且它會利用ngx_os_environ複製當前進程環境表指針environ(若是不瞭解能夠去參看APUE或者一些博客書籍瞭解)另外就如同上面提到的init_cycle,這時候它的做用就體現出來了,利用以前初始化的init_cycle->log,做爲內存分配時的錯誤記錄日誌,這也就是說,咱們不須要ngx_log_stderr()函數將錯誤寫入標準錯誤。
if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; }
仍是處理上面的參數,包括ngx_prefix,ngx_conf_file,ngx_conf_params,主要說下ngx_conf_file,若是沒設置該參數則將cycle->conf_file設置爲NGX_CONF_PATH,不然直接設置爲參數值。然後將會測試cycle->conf_file是不是一個絕對路徑,和上面的思路相同,若是不是,則將cycle->conf_prefix做爲前綴串(base目錄),緊接着根據cycle->conf_file從新設置cycle->conf_prefix(由於當前目錄可能改變了,若是想不明白能夠看上面的例子)
if (ngx_os_init(log) != NGX_OK) { return 1;
}
該函數用於獲得在當前操做系統下的頁大小ngx_pagesize和最大文件描述符ngx_max_sockets,而且檢測了當前所使用的CPU並得到L2高速cache的行大小,以此設置了所謂的ngx_cacheline_size的值(32,64,128)。
if (ngx_crc32_table_init() != NGX_OK) { return 1; }
該函數判斷當前的ngx_crc32_table_short(這是一個指針指向的是ngx_crc32_c文件中的現有靜態表)是否已經是根據ngx_cacheline_size內存對齊的,若是不是則從新分配一個循環冗餘檢驗表的內存,並根據上面獲得的ngx_cacheline_size進行內存對齊。爲何要這麼作呢?咱們知道CPU會將那些常用的數據放入到cache中,一旦數據命中,比從主存中取的速度快太多,所以若是咱們常用某些數據,可讓它們根據cache塊的大小進行內存對齊,這樣使得咱們能夠將這些數據放入高速cache中,使得它們的命中率更高,訪問速度更快。
ngx_slab_sizes_init();
有意思的是,上面全部函數都作了if檢查,可是這個函數沒有,實際上這個函數僅僅完成了對ngx_slab_max_size,ngx_slab_exact_size的初始化,它們是根據ngx_ox_init()函數中得到的ngx_pagesize(個人系統ubuntu19.04上是4096)來計算的。slab其實是一種在linux上的內存分配機制,它主要是針對一些常常進行分配和釋放的對象,這些對象通常佔據的內存很小,若是咱們常常釋放這些對象很容易就會形成內存碎片(也就是說有些釋放的連續內存很小以致於沒法進行重複使用),所以若是咱們使用一個slab分配器,將其size設定爲一個特定的大小,專門對這些小型的對象進行內存方面的管理,那麼就會防止出現上述的內存碎片現象了。(slab的介紹有點簡單了建議查閱其餘資料。。其實我有點好奇,若是這個slab只是在linux使用那麼是否nginx作了對其餘系統的檢測啥的...由於我暫時沒看到有..)
if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; }
這個函數用於繼承那些環境變量名爲NGINX_VAR的socket fd,並向cycle->listening動態數組添加這些fd,而且根據fd的值,從新設置ngx_listening_t中的字段。
if (ngx_preinit_modules() != NGX_OK) { return 1; }
這個函數日後就是重頭戲了...這個函數主要是初始化了一個ngx_modules列表的name和index,name由ngx_module_names列表獲得。可是說實話沒搞懂這個有什麼用,並且ngx_module_names這個字符串指針按道理應該是相同的,ngx_modules也沒見到它的內存分配在哪出現,或者說,這個函數若是初始的時候ngx_modules第一個元素即爲NULL,那麼實際上這個函數就沒意義了,或者說在worker進程會從新調用此函數?總之疑問不少...回頭若是瞭解了再來補充。。。
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; }
未完待續...先搞到這...作其餘的去了。。