nginx原始碼學習 主要的工作流程

2021-07-27 02:50:06 字數 3838 閱讀 4508

執行流程分析(以下分析基於linux,所以採用程序和子程序的說法,沒有用windows的程序和執行緒的說法)

main函式啟動:

1)初始化debug,ngx_debug_init

2)獲取命令列引數,ngx_get_options

3)初始化時間相關,ngx_time_init

4)初始化日誌相關,ngx_log_init

5)核心變數init_cycle,是乙個ngx_cycle_t物件(不是指標)

6)用該變數處理命令列引數,ngx_process_options

7)初始化crc32校驗表,ngx_crc32_table_init

8)初始化監聽socket,ngx_add_inherited_sockets

9)預初始化模組,ngx_preinit_modules

10)初始化init_cycle,ngx_init_cycle ————重點

11)建立pid檔案,ngx_create_pidfile

12)日誌輸出重定向到stderr,ngx_log_redirect_stderr

13)啟動單程序或多程序處理,ngx_single_process_cycle,ngx_master_process_cycle ————核心處理部分

從原始碼來看,只有linux下的核心處理,沒有windows的。

現在看ngx_master_process_cycle 的實現:(ngx_process_cycle.c 73行)

1)初始化訊號,包括:sigchld,sigalrm,sigio,sigint,ngx_reconfigure_signal,ngx_reopen_signal,ngx_noaccept_signal,ngx_terminate_signal,ngx_shutdown_signal,ngx_changebin_signal

2)啟動工作者程序,ngx_start_worker_processes ————重點(130行)

3)啟動緩衝管理程序,ngx_start_cache_manager_processes ————重點(132行)

4)進入for迴圈,直到某些條件觸發後退出迴圈,返回main函式,退出程式

5)for迴圈內:

(a)如果delay(延時),則設定乙個定時器setitimer(itimer_real, &itv, null

(b)更新緩衝的各個時間戳,ngx_time_update

(c)如果收到sigchld,會把ngx_reap設定為1,此時啟動子處理過程,ngx_reap_children

(d)如果沒有活動子過程,並且nginx_terminate或者ngx_quit被置為1,則退出nginx,ngx_master_process_exit(內部呼叫exit(0)直接退出整個程式)

(e)如果ngx_terminate被置為1,則發出ngx_terminate_signal訊號,如果delay達到1000以上,發出sigkill

(f)如果ngx_quit被置為1,則發出ngx_shutdown_signal訊號,關閉所有監聽socket

(g)如果ngx_reconfigure被置為1,重新初始化ngx_cycle_t,重新啟動工作程序和快取管理程序,發出ngx_shutdown_signal訊號停止本程序,如果是ngx_new_binary,說明是啟動新例項,則再建立新的工作程序和快取管理程序,和本程序並行

(h)如果ngx_restart置為1,則重啟工作程序和快取管理程序

(j)如果ngx_reopen置為1,則重新開啟日誌檔案

(k)如果ngx_change_binary置為1,則呼叫exec啟動新服務端例項

(l)如果ngx_noaccept置為1,則發出ngx_shutdown_signal訊號

現在看看ngx_start_worker_processes都做了什麼:(ngx_process_cycle.c 345行)

引數:ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type,第乙個是核心物件ngx_cycle_t,第二個是要啟動的程序數,預設是1,通過配置檔案修改,第三個是程序型別,在ngx_master_process_cycle中,該引數是ngx_process_respawn

在for迴圈中,建立n個程序,ngx_spawn_process,開啟n個通道,ngx_pass_open_channel

程序和通道資訊都儲存在全域性變數ngx_processes中。

現在看看ngx_spawn_process做了什麼:(ngx_process.c 87行)

引數:ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,

char *name, ngx_int_t respawn,第二個是真正的處理過程(這裡傳入的是ngx_worker_process_cycle),第三個是處理的資料(這裡是上一步傳入的迴圈變數i),第四個是程序名,第五個是建立型別,在ngx_start_worker_processes中傳入ngx_process_respawn

全域性變數ngx_last_process儲存了當前有多少程序被建立。

全域性變數ngx_process_t    ngx_processes[ngx_max_processes];儲存了所有的程序資訊。

在for迴圈中檢查每個ngx_processes元素,查詢乙個沒被使用的元素用來建立程序。

常量ngx_max_processes 1024,代表最多開啟1024個程序,如果上面的迴圈結束後s==它,說明沒有程序可以建立了,直接返回ngx_invalid_pid。

如果respawn!=ngx_process_detached(現在就是這種情況),建立tcpsocket對(兩個)儲存到ngx_processes[s].channel,設定兩個socket為非阻塞,對channel[0]設定標誌:fioasync:1,f_setown:ngx_pid,f_setfd:fd_cloexec,對channel[1]設定標誌:f_setfd:fd_cloexec

然後fork()子程序(實際的處理程序)。成功後根據respawn設定ngx_processes[s].的狀態值。

在fork()出來的子程序會呼叫傳入的proc,真正開啟迴圈處理過程。

現在看看實際迴圈程序ngx_worker_process_cycle:(ngx_process_cycle.c 727行)

首先用data,即迴圈時的i,作為程序序號,初始化程序,ngx_worker_process_init(同檔案,784行),該函式內部發出了第乙個ngx_read_event訊息。

然後在for迴圈中檢查ngx_process_events_and_timers,處理訊息。

實際處理函式ngx_process_events_and_timers:(ngx_event.c 194行)

檢視該檔案可以發現,該檔案是事件處理的統一呼叫層,根據最初模組初始化時的不同,產生了同名訊息吃處理函式的不同實現(使用不同的模組,包括epoll,kqueue,w32select等),該檔案呼叫統一的介面去處理事件,介面內部呼叫名稱相同、實際載入的處理函式巨集,比如ngx_add_event(wev, ngx_write_event, 0),ngx_del_event(wev, ngx_write_event, 0),再比如,ngx_epoll_add_event對應的就是ngx_add_event巨集。

到這裡,基本上就可以明白,nginx的高效,來自於底層網路模組,比如epoll的非同步非阻塞網路操作。所以熟悉epoll的用法,就可以自己實現乙個簡單高效的網路模組。libevent在linux下的高效吞吐其實也是來自於epoll,libevent本身的事件機制也不複雜。不過libevent在windows下用的是iocp,而nginx目前看是用的select,效率應該比libevent低。iocp本身效率是極其高的,但是開發模式的複雜度也非常搞,會導致業務邏輯複雜,反倒降低了效能。

nginx原始碼學習

nginx原始碼學習是乙個痛苦又快樂的過程,下面列出了一些nginx的學習資源。看了nginx原始碼,發現這是乙份完全沒有注釋,完全沒有配置文件的 這份注釋版原始碼會不斷進行更新的 好了,第乙個問題,nginx的main函式在 呢?src core nginx.c 第二個問題,nginx啟動的時候都...

3 1 學習nginx原始碼前的準備工作

winrar core下nginx的main函式 共享目錄不見了,一般可能是虛擬機器自帶的工具 vmware tools可能有問題 vmware tools是vmware虛擬機器自帶的一系列的增強工具,檔案共享功能就是wmware tools工具裡邊的 a 虛擬機器 重新安裝vmware tools...

nginx原始碼學習資源

nginx原始碼學習是乙個痛苦又快樂的過程,下面列出了一些nginx的學習資源。看了nginx原始碼,發現這是乙份完全沒有注釋,完全沒有配置文件的 這份注釋版原始碼會不斷進行更新的 好了,第乙個問題,nginx的main函式在 呢?src core nginx.c 第二個問題,nginx啟動的時候都...