nginx 原始碼學習筆記(二十)—— event 模組一 ——初始化
讀完之前的學習筆記,相信已經對nginx的啟動流程有了一定的認識,從這一節起我們想深入各個模組,學習各個模組的內的主要操作。
本文來自於:http://blog.csdn.net/lengzijian/article/details/7598996
今天我們就來學習下event模組,在之前的啟動裡多次提到了各個模組的鉤子函數,我們先來回想一下關於event模組鉤子函數的執行,也是event模組啟動的步驟:
1.創建韎
該方法,主要是創建了一個ngx_event_conf_t結構體,並且分配記憶體空間。
2.讀取設定檔:
例如讀取的檔案有如下行:
[cpp] view plaincopyprint?
events- {
- use oll; ;
- }
- 這個地方的events是block指令,在大括號內可以配置很多指令,這些指令定義在src/event/ngx_event.c中
static
ngx_command_t ngx_event_core_commands[] = {
x_string(
"worker_connections"- ),
- NGX_EVENT_CONF|NGX_CONF_TAKE1, NGX_EVENT_CONF|NGX_CONF_TAKE1, NGX_EVENT_CONF|NGX_CONF_TAKE1, NGX_EVENT_CONF|NGX_CONF1KE1, s,
- 0,
- 0, ...(此處省略)
- .
- NGX_EVENT_CONF|NGX_CONF_TAKE1,
- 0,
- 0,
- { ngx_string("use"
- ),
- NGX_EVENT_CONF|NGX_CONF_TAKE1, 0,
- 0, ull_command
- };
- 當解析到events是會回呼如下函數:
- [cpp] view plaincopyprint?
- src/event/ngx_event.c
- static ngx_conf_t *cf , ngx_command_t *cmd, void *conf)
- { char
- 無效 ***ctx;
- ngx_conf_t pcf;
- _ m;
- /*統計事件模組的數量並設定其索引*/
- ngx_event_max_module = 0;
- for
- (i = 0; ngx_modules[i]; i++) (ngx_modules[i]->type != NGX_ EVENT_MODULE) {
- 繼續;
- }
- ngx_modules[i]->ctx_index = ngx_event_max_module++;
- }
- ctx = ngx_pcalloc(cf-> pool, sizeof(void *));
- return
- NGX_CONF_ERROR;
- //每個事件模組分配空間,用於保存回應配置結構的位址
- *ctx = ngx_pcalloc( cf->pool, ngx_event_max_module * sizeof( void
- *)); {
- return NGX_CONF_ERROR; }
- for (i = 0; ngx_modules[i]; i++ ) {
- if (ngx_modules[i]- 繼續;
- }
- m = ngx_modules[i]-dx _conf鉤子函數,用於建立設定結構
- if (m->create_conf) {
- ,*)[ if
- ((*ctx )[ngx_modules[i]->ctx_index] == NULL) {
- }
- pcf = *cf;
- cf->ctx = ctx;
- cf->cmd_type = NGX_EVENT_CONF;
- //由於events為block指令,events域下方還可以設定許多其他指令,
- //例如之前提起的use等,現在開始解析events block中的指令,完成工作初始化。
- rv = ngx_conf_parse(cf, NULL);
- if (rv != NGX_CONF_OK)
- return rv;
- = 0; ngx_modules[i]; i++) {
- if
- (ngx_modul (ngx_modul. type != NGX_EVENT_MODULE) {
- }
- m = ngx_modules[i]->ctx; init_conf函數,初始化配置結構
- if rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i] ->ctx_index]);
- if (rv
- return rv; }
- }
- return NGX_CONF_OK;
ngx_events_block()函數中最重要的一個過程就是呼叫ngx_conf_parse(cf, NULL),此處呼叫ngx_conf_parse()的作用就是完成設定檔中events{}這個block的解析,從而呼叫其下所有的設定檔指令的回呼函數,完成解析設定檔的初始化工作。但這裡我個人有個問題,待問完前輩之後,在指明問題和答案******。
2.初始化conf(init_conf)
ngx_event_init_conf()
該方法,主要是初始化ngx_event_conf_t結構體。
3.ngx_event_module_init
從名字上看是模組的初始化操作,但是縱觀各個模組原始碼,發現很多模組都沒有init回呼函數。這裡本人也在糾結為什麼,希望在學完全部代碼後,能找到答案。
[cpp] view plaincopyprint?
- src/event/ngx_event.c
- static ngx_int_t
- {
- 無效
- u_char *共享;
- size_t 尺寸, cl;
- ngx_shm_t shm;
- ngx_time_t *tp;
- ngx_core_conf_t *ccf;
- ngx_event_conf_t *ecf;
- // = ngx_get_conf(cycle->conf_ctx, ngx_事件模組);
- if
- (cf == NULL) {
- 「設定中沒有「事件」部分」); 「配置中沒有「事件」部分」); 「
- 回
- NGX_ERROR;
- //取得ngx_event_core_module模組的設定結構
- ecf = (cf.
- //檢視是否為event中的模組,例如使用。 。 。 。
- if (!ngx_test_config && ngx_process ngx_log_error(NGX_LOG_NOTICE, cycle->script 0,
- event method", ecf->name);
- }
- ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
- //將 ngx_timer_resolution = ccf->timer_resolution;
- #if ! (NGX_WIN32) {
- struct
- rlimit rlmt;
- 拾取man getrlimit
- if (getrlimit ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- RLIMIT_NOFILE) failed, ignored");
- } else {
- //如果 //且ngx_core_module最大連線數無限制
- /或ngx_event_core_module連線數大於ngx_core_module最大連線數
- && (ccf->rlimit_nofile == NGX_CONF_UNSET || ecf->connections > (ngx_uint_t) ccf->親素
- limit = (ccf->rlimit_nofile == NGX_CONF_UNSET (ngx_int_t) rlmt.rlim_cur : ccf ->rlimit_nofile;
- "%ui worker_connections are
- "open file resource limit: %i",
- ecf->connections, limit);
- }
- }
- }
- #endif /* !(NGX_WIN32) */
- //如果關閉了master進程,就返回是單一工作方式,
- //之後的操作時建立共享記憶體實作鎖等工作,單進程不需要。
- if (ccf->master == 0) { NGX_OK;
- } 已經有accept互斥了,不需要再重複創建了
- if
- (ngx_accept_mutex_ptrif (ngx_accept_mutex_ptr)) return NGX_OK;
- }
- /* cl should be equal or bigger
- cl = 128;
- //在這裡創造sizeize大小的大小的大小共享內存,這塊共享記憶體將被分成三段
- size = cl
- + cl /* + cl;
- /* ngx_temp_number */ //準備共享內存,大小為size,命名nginx_shared_zone,
- shm.size
- shm.size shm.size
- shm.name.len = sizeof("nginx_shared_zone" ); *)
- "nginx_shared_zone"; shm .log = cycle->log;
- if (ngx_shm_alloc(&shm) != NGX_OK ) {
- return NGX_ERROR; //取得起始位址保存 shared = shm.addr;
- //accept互斥體取得共享記憶體的第一段cl大小記憶體
- ngx_accept_mutex.spin = (ngx_uint_t) -1;
- /*創建accept互斥體
- 就是使用的這段共享記憶體來實現accept互斥體;否則,將使用檔案鎖定
- 來實現accept互斥體。
- accept 互斥體的作用是:避免驚群與實現worker進程的負載平衡。
- */ (ngx_shmtx_create(&ngx_accept_mutex, shared, cycle->lock_file.data)
- { return
- Sharp ngx_atomic_t *) (shared + 1 * cl);
- , 1);
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_log_debug2(NGX_LOG_DEBUGcleEVENT, cycy-> log, 0,
- ngx_connection_counter, *ngx_connection_counter); ngx_connection_counter, *ngx_connection_counter);
- ngx_temp_number = (ngx_atomic_t *) (shared + 2 tp = ngx_timeofday();
- ngx_
- return
- 4.ngx_event_process_init在先前的worker進程分析中有提到過,當創建了一個worker進程後,worker進程首先就會做進程的初始化工作,此時會呼叫ngx_event_process_init函數。
- [cpp] view plaincopyprint?
- src/event/ngx_event.c
- static ngx_int_t o_p )
- {
- ngx_uint_t ngx_event_t *rev, *wev;
- ngx_listening_t *c, *next, *old;
- ngx_core_conf_t *ccf;
- ngx_event_module_t *module;
- //與先前相同,取得反應模組 (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
- ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
- ,已經創建了accept_mutex
- //才打開accept互斥體
- if (ccf->master && ccf->worker_processes
- ngx_use_accept_mutex = 1; //使用互斥物
- ngx_accept_mutex_held = 0; ngx_accept_mutex_delay = ecf->accept_mutex_delay;//爭搶互斥體失敗後,等待下次爭搶時間間隔
- } ngx_use_accept_mutex = 0;
- }
- //先未講
- #endif器,此處將會建立一顆紅黑樹,來維護計時器,之後會詳細解說
- if (ngx_event_timer_init return
- NGX_ERROR;
- } }
- for
- (m = 0; ngx_modules[m]; m++) { NGX_EVENT_MODULE模組
- if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
- }
- //非use配置指令指定的模組跳過,linux預設epoll es[m]->ctx_index != ecf->use) {
- continue;
- module = ngx_modules[m]->ctx;
- 由於nginx實現了許多事件模組 (這些模組位於src/event/modules目錄中),所以nginx對時間模組進行了一層抽象,
- 方便了不同的系統使用不同的事件模型,也方便擴充新的時間模型,我們的重點應該
- _ module->actions結構封裝了
- epoll的所有介面函數。 nginx就是透過actions結構將epoll註冊到事件抽象層。
- actions的種類是ngx_event_action_t,位於src/event/ngx_event.h
- 這些特定的內容會在下一節中重點解說。
- */
- if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
- /* fatal */
- exit(2);
- break
- ;
- 內容
- //創建全域的ngx_connection_t數組,保存所有的connection worker進程中執行的,所以每個worker都有自己的connection陣列
- cycle->connections = t) * cycle->connection_n, cycle->log);
- if ( cycle->connections == NULL) {
- return
- c = cycle->connections; 🎠 //建立一個讀取事件陣列
- cycle->read_events = ngx_alloc(size (ngx_event_t) if
- (cycle->read_events == NULL) { }
- rev = cycle->read_events; for (i = 0; i connection_n; i++) {
- rev[i].instance = 1;
- #if (NGX_THREADS)
- rev[i].lock = own_lock = &c[i].lock; # endif
- }
- //建立一個寫事件佇列
- cycle->connection_n,
- if
- (cycle->write_events == NULL) { OR;
- }
- cle.
- for (i = 0; i 連接_n; i++) { = 1;
- #if (NGX_THREADS) wev[i].lock = &c[i].lock;
- #endif }
- i = 循環-
- //初始化連接佇列
- do
- do
- i--;
- c[i].read = &cycle->read_events[i];
- c [i].write = &cycle->write_events[i]; c[i].fd = (ngx_socket_t) c[i].fd = (ngx_socket_t) c[i].fd = (ngx_socket_t) c
- 下一個= &c[i];
- #if (NGX_THREADS)
- #endif
- }while (i);
- ->free_connection_n = cycle->connection_n;
- /* forforforforforforforfor號each listening socket */
- //每個監聽套接字從一個接合 ls = cycle->listening.elts;
- for (i = 0; i listening.nelts; i++) { 在ton中取得新的連線solt
- c = ngx_get_connection(ls[i].fd, cycle->log);
- return NGX_ERROR;
- NGX_ERROR;
- }
- c->log = &ls[i].log; c->聽= &ls[i];
- ls[i].connection = c ;
- rev = c->閱讀; ->log = c->log;
- rev->accept = 1; //讀取時間問 //簡潔
- #endif
- if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) & NGX_USE_ IOC
- P_EVENT)) if (ls[i].previous) {
- * 刪除舊的接受事件綁定 * 舊循環讀取事件陣列
- 的舊式 = ls [i].previous->連接;
- NGX_CLOSE_EVENT)
- { 回復
- NGX_ERR或; }
- }
- }
- //登錄監聽套介面毒事件的回呼函數 rev->handler = ngx_event_accept; 暫時不將監聽套接字放入epoll中,而是
- //worker
- if (ngx_use_accept_mutex) {
- continue;
- }
- if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
- if (ngx_add_conn(c) == NGX_ERROR)
- return NGX_ERROR;
- } else {
- //沒有使用accept互斥體,因此將此監聽套接字放入epoll中。
- if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
- return NGX_ERROR;
- } }
- #endif
- return NGX_OK;
- }
- } ,事件驅動的初始化已經完成。 以上就介紹了nginx 原始碼學習筆記(二十)—— event 模組一 ——初始化,包括了IOC,計數器方面的內容,希望對PHP教程有興趣的朋友有所幫助。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

「你的組織要求你更改PIN訊息」將顯示在登入畫面上。當在使用基於組織的帳戶設定的電腦上達到PIN過期限制時,就會發生這種情況,在該電腦上,他們可以控制個人設備。但是,如果您使用個人帳戶設定了Windows,則理想情況下不應顯示錯誤訊息。雖然情況並非總是如此。大多數遇到錯誤的使用者使用個人帳戶報告。為什麼我的組織要求我在Windows11上更改我的PIN?可能是您的帳戶與組織相關聯,您的主要方法應該是驗證這一點。聯絡網域管理員會有所幫助!此外,配置錯誤的本機原則設定或不正確的登錄項目也可能導致錯誤。即

Windows11將清新優雅的設計帶到了最前沿;現代介面可讓您個性化和更改最精細的細節,例如視窗邊框。在本指南中,我們將討論逐步說明,以協助您在Windows作業系統中建立反映您的風格的環境。如何更改視窗邊框設定?按+開啟“設定”應用程式。 WindowsI前往個人化,然後按一下顏色設定。顏色變更視窗邊框設定視窗11「寬度=」643「高度=」500「>找到在標題列和視窗邊框上顯示強調色選項,然後切換它旁邊的開關。若要在「開始」功能表和工作列上顯示主題色,請開啟「在開始」功能表和工作列上顯示主題

預設情況下,Windows11上的標題列顏色取決於您選擇的深色/淺色主題。但是,您可以將其變更為所需的任何顏色。在本指南中,我們將討論三種方法的逐步說明,以更改它並個性化您的桌面體驗,使其具有視覺吸引力。是否可以更改活動和非活動視窗的標題列顏色?是的,您可以使用「設定」套用變更活動視窗的標題列顏色,也可以使用登錄編輯程式變更非活動視窗的標題列顏色。若要了解這些步驟,請前往下一部分。如何在Windows11中變更標題列的顏色? 1.使用「設定」應用程式按+開啟設定視窗。 WindowsI前往“個人化”,然

工作列縮圖可能很有趣,但它們也可能分散注意力或煩人。考慮到您將滑鼠懸停在該區域的頻率,您可能無意中關閉了重要視窗幾次。另一個缺點是它使用更多的系統資源,因此,如果您一直在尋找一種提高資源效率的方法,我們將向您展示如何停用它。不過,如果您的硬體規格可以處理它並且您喜歡預覽版,則可以啟用它。如何在Windows11中啟用工作列縮圖預覽? 1.使用「設定」應用程式點擊鍵並點選設定。 Windows按一下系統,然後選擇關於。點選高級系統設定。導航至“進階”選項卡,然後選擇“效能”下的“設定”。在「視覺效果」選

您是否在Windows安裝程式頁面上看到「出現問題」以及「OOBELANGUAGE」語句? Windows的安裝有時會因此類錯誤而停止。 OOBE表示開箱即用的體驗。正如錯誤提示所表示的那樣,這是與OOBE語言選擇相關的問題。沒有什麼好擔心的,你可以透過OOBE螢幕本身的漂亮註冊表編輯來解決這個問題。快速修復–1.點選OOBE應用底部的「重試」按鈕。這將繼續進行該過程,而不會再打嗝。 2.使用電源按鈕強制關閉系統。系統重新啟動後,OOBE應繼續。 3.斷開系統與網際網路的連接。在脫機模式下完成OOBE的所

在Windows11上的顯示縮放方面,我們都有不同的偏好。有些人喜歡大圖標,有些人喜歡小圖標。但是,我們都同意擁有正確的縮放比例很重要。字體縮放不良或圖像過度縮放可能是工作時真正的生產力殺手,因此您需要知道如何自訂以充分利用系統功能。自訂縮放的優點:對於難以閱讀螢幕上的文字的人來說,這是一個有用的功能。它可以幫助您一次在螢幕上查看更多內容。您可以建立僅適用於某些監視器和應用程式的自訂擴充功能設定檔。可以幫助提高低階硬體的效能。它使您可以更好地控制螢幕上的內容。如何在Windows11

螢幕亮度是使用現代計算設備不可或缺的一部分,尤其是當您長時間注視螢幕時。它可以幫助您減輕眼睛疲勞,提高易讀性,並輕鬆有效地查看內容。但是,根據您的設置,有時很難管理亮度,尤其是在具有新UI更改的Windows11上。如果您在調整亮度時遇到問題,以下是在Windows11上管理亮度的所有方法。如何在Windows11上變更亮度[10種方式解釋]單一顯示器使用者可以使用下列方法在Windows11上調整亮度。這包括使用單一顯示器的桌上型電腦系統以及筆記型電腦。讓我們開始吧。方法1:使用操作中心操作中心是訪問

Windows上的啟動過程有時會突然轉向顯示包含此錯誤代碼0xc004f069的錯誤訊息。雖然啟動程序已經聯機,但一些運行WindowsServer的舊系統可能會遇到此問題。透過這些初步檢查,如果這些檢查不能幫助您啟動系統,請跳到主要解決方案以解決問題。解決方法–關閉錯誤訊息和啟動視窗。然後,重新啟動電腦。再次從頭開始重試Windows啟動程序。修復1–從終端啟動從cmd終端啟動WindowsServerEdition系統。階段–1檢查Windows伺服器版本您必須檢查您使用的是哪種類型的W
