**
本文著手分析一下worker程序的情況。首先找到worker程序的入口地方——ngx_worker_process_cycle。這個函式不光是worker程序的入口函式,同時也是worker程序迴圈工作的主體函式,看函式名含有乙個cycle嘛。進入這個cycle函式,第一件事就是呼叫ngx_worker_process_init(cycle, 1);對worker程序進行初始化操作。先看看這個worker程序的初始化過程。
[cpp]view plain
copy
?ngx_process = ngx_process_worker;
if(ngx_set_environment(cycle, null) == null)
進入初始化就將全域性變數ngx_process設定為worker程序的標誌,由於這個變數是從master程序複製過來的,所以沒設定前就是master程序的標誌。然後設定相應的環境變數。接下去就是設定了一些列的資源限制,id等玩意,這裡就忽略**了。
[cpp]view plain
copy
?for
(i = 0; ngx_modules[i]; i++)
} }
此處迴圈呼叫每個模組的init_process,完成每個模組自定義的程序初始化操作,一般在模組定義的時候設定這個**指標的值,即註冊乙個函式給它。做模組開發的時候,貌似使用得挺少的,遇到的時候好好關注下。
[cpp]view plain
copy
print?/*
此處迴圈用於關閉其他worker程序的無用channel資源
*/for
(n = 0; n < ngx_last_process; n++)
/*全域性變數ngx_process_slot的值是建立worker程序的時候,從
master程序複製過來的,所以此處ngx_process_slot就指本worker
程序在ngx_process_slot陣列中的索引位置。此處不處理本worker
程序,所以跳過。
*/if
(n == ngx_process_slot)
/*channel不存在,繼續跳過。
*/if
(ngx_processes[n].channel[1] == -1)
/*ngx_processes陣列中儲存的是每個worker程序的資源,是master程序負責建立的。
因此建立乙個worker程序的時候,就一同將這些資源複製過來了,所以此處就關閉
無用的channel——其他worker程序的讀端檔案描述符,保留寫端檔案描述符做
worker間的通訊之用。
*/if
(close(ngx_processes[n].channel[1]) == -1)
} /*
關閉本worker程序channel的寫端檔案描述符,因為每個worker程序只從自己的channel
上讀,而不會寫。寫自己channel的是master和其他worker程序。這也是上面為什麼要
關閉其他worker程序channel的讀端。
*/if
(close(ngx_processes[ngx_process_slot].channel[0]) == -1)
針對這段**採用直接注釋**的方式進行分析,感覺挺自然的,還不錯,以後碰到比較長的**段都採用這種方式進行了。
[cpp]view plain
copy
print?if
(ngx_add_channel_event(cycle, ngx_channel, ngx_read_event,
ngx_channel_handler)
== ngx_error)
ngx_channel就是worker程序channel的讀端,這裡呼叫ngx_add_channel_event將channel放入nginx關心的集合中,同時關注起這個channel上的讀事件,也即這個channel上有資料到來後,就立馬採取讀channel操作。此處的新增乙個channel的讀事件是worker程序初始化的關鍵之處。到此,初始化過程就結束了,回到worker迴圈主體看看吧。
[cpp]view plain
copy
?for
( ;; )
} /*
處理完所有事件後,呼叫ngx_worker_process_exit函式,worker程序退出。
*/if
(ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
} ngx_log_debug0(ngx_log_debug_event, cycle->log, 0,
"worker cycle"
);
/*這裡是worker程序處理事件的核心開始。也即是,worker程序從裡開始做一些特定的事情了,
我們完全可以修改此處的**,讓nginx為我們做一些其他的事情,呵呵。
*/ngx_process_events_and_timers(cycle);
/*worker程序收到了sigint訊號,退出。
*/if
(ngx_terminate)
/*worker程序收到了sigquit訊號,如果此時worker程序不是出於exiting狀態,
就將設定ngx_exiting為1,讓其進入exiting狀態;同時關閉監聽套介面。
*/if
(ngx_quit)
} /*
worker程序收到了sigusr1訊號
*/if
(ngx_reopen)
} 通過上述分析發現worker程序的cycle比master簡單不少啊,到此,worker程序的大體框架就差不多了。
Nginx原始碼分析之ngx array t
ngx array t是乙個順序容器,類似於stl中的vector可以動態擴容。原始碼位置 nginx src core ngx array.h nginx src core ngx array.c typedef struct ngx array s ngx array t struct ngx ...
nginx原始碼分析之ngx list
ngx list t是nginx封裝鍊錶的容器,其原始碼位於 宣告 nginx src core ngx list.h 定義 nginx src core ngx list.c 在nginx中使用頻繁,例如http頭部就是用ngx list t儲存的。nginx的鍊錶 頭 結構為ngx list t...
nginx 原始碼分析
近期準備研究一下nginx原始碼,此處記錄一下。計畫 1 了解evan miller 的文章 2 了解nginx的組織架構 3 了解nginx的基本資料結構 4 熟悉nginx的主要module及執行機制,主要是core http event os 5 簡單的module開發及測試 一 準備 為了方...