1. 程式人生 > >Nginx原始碼分析---模組初始化

Nginx原始碼分析---模組初始化

Content

0. 

1. nginx有哪些模組?

2. nginx如何描述這些模組?

2.1 模組資料結構

2.1.1 ngx_module_t結構

2.1.2 ngx_command_t結構

2.2 模組類圖

3. nginx如何組織這些模組?

3.1 全域性陣列ngx_modules

3.2 模組組織結構圖

4. nginx的模組種類

5. nginx如何初始化這些模組?

5.1 靜態初始化

5.2 動態初始化

5.2.1 index欄位的初始化

5.2.2 ctx_index欄位的初始化

5.2.3 其他初始化

6. 小結

0. 

本文以

nginx-1.0.4版本為例,介紹nginx的模組及其初始化。.表示nginx-1.0.4原始碼目錄,本文為/usr/src/nginx-1.0.4

1. nginx有哪些模組?

要知道nginx有哪些模組,一個快速的方法就是編譯nginx。編譯之後,會在原始碼根目錄下生成objs目錄,該目錄中包含有ngx_auto_config.hngx_auto_headers.h,以及ngx_modules.c檔案,當然,還有Makefile檔案等。

其中,生成的ngx_modules.c檔案中,重新集中申明(使用extern關鍵字)nginx配置的所有模組,這些模組可通過編譯前的configure

命令進行配置,即設定哪些模組需要編譯,哪些不被編譯。如下。

00001:

00002: #include

00003: #include

00004:

00005:

00006:

00007: extern ngx_module_t ngx_core_module;

00008: extern ngx_module_t ngx_errlog_module;

00009: extern ngx_module_t ngx_conf_module;

00010: extern ngx_module_t ngx_events_module;

00011: extern ngx_module_t ngx_event_core_module;

00012: extern ngx_module_t 

ngx_epoll_module;

00013: extern ngx_module_t ngx_http_module;

00014: extern ngx_module_t ngx_http_core_module;

00015: extern ngx_module_t ngx_http_log_module;

00016: extern ngx_module_t ngx_http_upstream_module;

00017: extern ngx_module_t ngx_http_static_module;

00018: extern ngx_module_t ngx_http_autoindex_module;

00019: extern ngx_module_t ngx_http_index_module;

00020: extern ngx_module_t ngx_http_auth_basic_module;

00021: extern ngx_module_t ngx_http_access_module;

00022: extern ngx_module_t ngx_http_limit_zone_module;

00023: extern ngx_module_t ngx_http_limit_req_module;

00024: extern ngx_module_t ngx_http_geo_module;

00025: extern ngx_module_t ngx_http_map_module;

00026: extern ngx_module_t ngx_http_split_clients_module;

00027: extern ngx_module_t ngx_http_referer_module;

00028: extern ngx_module_t ngx_http_rewrite_module;

00029: extern ngx_module_t ngx_http_proxy_module;

00030: extern ngx_module_t ngx_http_fastcgi_module;

00031: extern ngx_module_t ngx_http_uwsgi_module;

00032: extern ngx_module_t ngx_http_scgi_module;

00033: extern ngx_module_t ngx_http_memcached_module;

00034: extern ngx_module_t ngx_http_empty_gif_module;

00035: extern ngx_module_t ngx_http_browser_module;

00036: extern ngx_module_t ngx_http_upstream_ip_hash_module;

00037: extern ngx_module_t ngx_http_stub_status_module;

00038: extern ngx_module_t ngx_http_write_filter_module;

00039: extern ngx_module_t ngx_http_header_filter_module;

00040: extern ngx_module_t ngx_http_chunked_filter_module;

00041: extern ngx_module_t ngx_http_range_header_filter_module;

00042: extern ngx_module_t ngx_http_gzip_filter_module;

00043: extern ngx_module_t ngx_http_postpone_filter_module;

00044: extern ngx_module_t ngx_http_ssi_filter_module;

00045: extern ngx_module_t ngx_http_charset_filter_module;

00046: extern ngx_module_t ngx_http_userid_filter_module;

00047: extern ngx_module_t ngx_http_headers_filter_module;

00048: extern ngx_module_t ngx_http_copy_filter_module;

00049: extern ngx_module_t ngx_http_range_body_filter_module;

00050: extern ngx_module_t ngx_http_not_modified_filter_module;

00051:

很顯然,這些模組均是在此處用extern進行申明,以表明其他模組可以訪問,而對其本身的定義和初始化ngx_module_t結構在其對應的.c檔案中進行。例如,ngx_core_module模組便是在./src/core/nginx.c檔案中定義並進行靜態初始化。實際上,ngx_core_module是一個全域性的結構體物件,其他模組類同。如下。

ngx_module_t  ngx_core_module = {

    NGX_MODULE_V1,

    &ngx_core_module_ctx,                  /* module context */

    ngx_core_commands,                     /* module directives */

    NGX_CORE_MODULE,                       /* module type */

    NULL,                                  /* init master */

    NULL,                                  /* init module */

    NULL,                                  /* init process */

    NULL,                                  /* init thread */

    NULL,                                  /* exit thread */

    NULL,                                  /* exit process */

    NULL,                                  /* exit master */

    NGX_MODULE_V1_PADDING

};

2. nginx如何描述這些模組?

2.1 模組資料結構

2.1.1 ngx_module_t結構

nginx的模組化架構最基本的資料結構為ngx_module_t,因此,此處,我們先分析這個結構,在./src/core/ngx_conf_file.h檔案中定義。如下,//後的內容為筆者加入的注視。

00107: #define NGX_MODULE_V1    0000001         //該巨集用來初始化前7個欄位

00108: #define NGX_MODULE_V1_PADDING 0000000//該巨集用來初始化最後8個欄位

00109:

00110: struct ngx_module_s{

00111:    ngx_uint_t    ctx_index;  //分類模組計數器

00112:    ngx_uint_t    index;      //模組計數器

00113:

00114:    ngx_uint_t    spare0;

00115:    ngx_uint_t    spare1;

00116:    ngx_uint_t    spare2;

00117:    ngx_uint_t    spare3;

00118:

00119:    ngx_uint_t    version;    //版本

00120:

00121:    void          *ctx;       //該模組的上下文,每個種類的模組有不同的上下文

00122:    ngx_command_t *commands;  //該模組的命令集,指向一個ngx_command_t結構陣列

00123:    ngx_uint_t    type;       //該模組的種類,為core/event/http/mail中的一種

00124:    //以下是一些callback函式

00125:    ngx_uint_t    (*init_master)(ngx_log_t *log);      //初始化master

00126:

00127:    ngx_uint_t    (*init_module)(ngx_cycle_t *cycle);  //初始化模組

00128:

00129:    ngx_uint_t    (*init_process)(ngx_cycle_t *cycle); //初始化工作程序

00130:    ngx_uint_t    (*init_thread)(ngx_cycle_t *cycle);  //初始化執行緒

00131:    void          (*exit_thread)(ngx_cycle_t *cycle);  //退出執行緒

00132:    void          (*exit_process)(ngx_cycle_t *cycle); //退出工作程序

00133:

00134:    void          (*exit_master)(ngx_cycle_t *cycle);  //退出master

00135:

00136:    uintptr_t     spare_hook0;  //這些欄位貌似沒用過

00137:    uintptr_t     spare_hook1;

00138:    uintptr_t     spare_hook2;

00139:    uintptr_t     spare_hook3;

00140:    uintptr_t     spare_hook4;

00141:    uintptr_t     spare_hook5;

00142:    uintptr_t     spare_hook6;

00143:    uintptr_t     spare_hook7;

00144: };

其中,init_master, init_module, init_process, init_thread, exit_thread, exit_process, exit_master分別在初始化master、初始化模組、初始化工作程序、初始化執行緒、退出執行緒、退出工作程序、退出master時被呼叫。

2.1.2 ngx_command_t結構

模組的命令集commands指向一個ngx_command_t結構陣列,在./src/core/ngx_conf_file.h檔案中定義。如下,//後的內容為筆者加入的注視。

00077: struct ngx_command_s {

00078:    ngx_str_t     name;  //命令名

00079:    ngx_uint_t    type;  //命令型別

00080:    char          *(*set)(ngx_conf_t *cfngx_command_t *cmdvoid *conf);

00081:    ngx_uint_t    conf;

00082:    ngx_uint_t    offset;

00083:    void          *post;

00084: };

00085:

00086: #define ngx_null_command ngx_null_string0NULL00NULL }  //空命令

2.2 模組類圖

nginxC語言開發的開源高效能web server,其程式碼中大量使用了callback方式,例如模組結構ngx_module_t中的init_master等。實際上,我們可以將ngx_module_t看作C++的一個類,其中的資料欄位便是其屬性,而那些callback便是該類的操作。

——這應該就是nginx的模組化思想。畫出的ngx_module_t的類圖如下。

3.nginx如何組織這些模組?

3.1 全域性陣列ngx_modules

由第1節,我們知道,nginx擁有幾十個模組,那麼,這些模組是如何組織的呢?

——儲存在一個全域性指標陣列ngx_modules[]中,陣列的每一個元素均為一個全域性ngx_module_t物件的指標。如下。請參考./objs/ngx_modules.c檔案中的定義。

00052: ngx_module_t *ngx_modules[] {

00053:    &ngx_core_module,

00054:    &ngx_errlog_module,

00055:    &ngx_conf_module,

00056:    &ngx_events_module,

00057:    &ngx_event_core_module,

00058:    &ngx_epoll_module,

00059:    &ngx_http_module,

00060:    &ngx_http_core_module,

00061:    &ngx_http_log_module,

00062:    &ngx_http_upstream_module,

00063:    &ngx_http_static_module,

00064:    &ngx_http_autoindex_module,

00065:    &ngx_http_index_module,

00066:    &ngx_http_auth_basic_module,

00067:    &ngx_http_access_module,

00068:    &ngx_http_limit_zone_module,

00069:    &ngx_http_limit_req_module,

00070:    &ngx_http_geo_module,

00071:    &ngx_http_map_module,

00072:    &ngx_http_split_clients_module,

00073:    &ngx_http_referer_module,

00074:    &ngx_http_rewrite_module,

00075:    &ngx_http_proxy_module,

00076:    &ngx_http_fastcgi_module,

00077:    &ngx_http_uwsgi_module,

00078:    &ngx_http_scgi_module,

00079:    &ngx_http_memcached_module,

00080:    &ngx_http_empty_gif_module,

00081:    &ngx_http_browser_module,

00082:    &ngx_http_upstream_ip_hash_module,

00083:    &ngx_http_stub_status_module,

00084:    &ngx_http_write_filter_module,

00085:    &ngx_http_header_filter_module,

00086:    &ngx_http_chunked_filter_module,

00087:    &ngx_http_range_header_filter_module,

00088:    &ngx_http_gzip_filter_module,

00089:    &ngx_http_postpone_filter_module,

00090:    &ngx_http_ssi_filter_module,

00091:    &ngx_http_charset_filter_module,

00092:    &ngx_http_userid_filter_module,

00093:    &ngx_http_headers_filter_module,

00094:    &ngx_http_copy_filter_module,

00095:    &ngx_http_range_body_filter_module,

00096:    &ngx_http_not_modified_filter_module,

00097:    NULL

00098: };

00099:

3.2 模組組織結構圖

44個模組,這些模組的組織結構圖如下所示,因模組較多,圖中只畫出一部分有代表性的重要模組。

4. nginx的模組種類

在對全域性陣列ngx_modules進行初始化時,即對每一個模組進行了靜態初始化。其中對模組的type欄位的初始化是通過以下4個巨集進行的。

(1) 檔案./src/core/ngx_conf_file.h

#defineNGX_CORE_MODULE0x45524F43/* "CORE" */

#defineNGX_CONF_MODULE0x464E4F43/* "CONF" */

(2) 檔案./src/event/ngx_event.h

#define NGX_EVENT_MODULE      0x544E5645  /* "EVNT" */

(3) 檔案./src/http/ngx_http_config.h

#define NGX_HTTP_MODULE       0x50545448  /* "HTTP" */

相關推薦

Nginx原始碼分析---模組初始

Content 0. 序 1. nginx有哪些模組? 2. nginx如何描述這些模組? 2.1 模組資料結構 2.1.1 ngx_module_t結構 2.1.2 ngx_command_t結構 2.2 模組類圖 3. nginx如何組織這些模組?

nginx原始碼閱讀(二).初始:main函式及ngx_init_cycle函式

前言 在分析原始碼時,我們可以先把握主幹,然後其他部分再挨個分析就行了。接下來我們先看看nginx的main函式幹了些什麼。 main函式 這裡先介紹一些下面會遇到的變數型別: ngx_int_t: typedef intptr_t ngx_int_t; 64位機器上,intptr_

SpringMVC原始碼分析--容器初始(四)FrameworkServlet

一下SpringMVC配置檔案的地址contextConfigLocation的配置屬性,然後其呼叫的子類FrameworkServlet的initServletBean方法。 其實FrameworkServlet是springMVC初始化IOC容器的核心,通過讀取配置的c

springMVC原始碼分析--容器初始(一)ContextLoaderListener

在spring Web中,需要初始化IOC容器,用於存放我們注入的各種物件。當tomcat啟動時首先會初始化一個web對應的IOC容器,用於初始化和注入各種我們在web執行過程中需要的物件。當tomcat啟動的時候是如何初始化IOC容器的,我們先看一下在web.xml中經常看

SpringMVC原始碼分析--容器初始(五)DispatcherServlet

上一篇部落格SpringMVC原始碼分析--容器初始化(四)FrameworkServlet我們已經瞭解到了SpringMVC容器的初始化,SpringMVC對容器初始化後會進行一系列的其他屬性的初始化操作,在SpringMVC初始化完成之後會呼叫onRefresh(wac

SpringMVC原始碼分析--容器初始(三)HttpServletBean

在上一篇部落格 springMVC原始碼分析--容器初始化(二)DispatcherServlet中,我們隊SpringMVC整體生命週期有一個簡單的說明,並沒有進行詳細的原始碼分析,接下來我們會根據部落格中提供的springMVC的生命週期圖來詳細的對SpringMVC的

精盡 MyBatis 原始碼分析 - MyBatis 初始(一)之載入 mybatis-config.xml

> 該系列文件是本人在學習 Mybatis 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋([Mybatis原始碼分析 GitHub 地址](https://github.com/liu844869663/mybatis-3)、[Mybatis-Spring 原始碼分析 GitHub 地址

精盡MyBatis原始碼分析 - MyBatis初始(二)之載入 Mapper 介面與 XML 對映檔案

> 該系列文件是本人在學習 Mybatis 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋([Mybatis原始碼分析 GitHub 地址](https://github.com/liu844869663/mybatis-3)、[Mybatis-Spring 原始碼分析 GitHub 地址

精盡MyBatis原始碼分析 - MyBatis初始(四)之 SQL 初始(下)

> 該系列文件是本人在學習 Mybatis 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋([Mybatis原始碼分析 GitHub 地址](https://github.com/liu844869663/mybatis-3)、[Mybatis-Spring 原始碼分析 GitHub 地址

nginx原始碼分析(5)——監聽socket初始

在nginx原始碼分析(4)中,看到了nginx的事件模型,但其中沒有介紹監聽socket的初始化。而對於web server來說,需要通過監聽socket來監聽客戶端的連線等。本篇將會具體介紹這方面的內容。還記得在前文介紹ngx_cycle_t結構時,它具有一個listening屬性,是一個數組,

Nginx原始碼分析與實踐---(一)編寫一個簡單的Http模組

在上一節中,我們通過修改配置檔案,便能讓nginx去訪問我們寫的html檔案,並返回給瀏覽器。問題是:nginx是如何檢測到我們寫的配置項的?檢測到後,nginx又是如何知道該進行什麼操作的? 本節通過親自實踐,寫一個經典的Hello World模組來了解相應的流程是如何進行的。我們採用自上

JFinal初始分析-常量初始-1

但是 nts 3.0 nal ring 問題 簡單 環境配置 comment spring自己基本不熟悉,因為超多的xml配置太繁瑣,就放棄了。自己也不是專做開發的,主要工作是運維。jfianl的出現,無xml配置,令人驚喜。 當時就想學一下這個框架的設計,就找博文來讀,但

spring源碼分析初始過程

源碼分析 true singleton 存在 factory 源碼 org 包含 eric 1.org.springframework.web.context.ContextLoaderListener 一個ServletContextListener,web容器啟動監聽器

4.4 模組初始與結束

4.4.1模組入口程式碼  編譯器為每個Delphi模組(可執行程式、動態連結庫或包)生成模組入口程式碼。同類型的程式或模組,其入口程式碼是相同的。  編譯器為可執行程式.EXE)生成的入口程式碼為: Project1.dpr.9:begin 0044CA9855push      ebp 0044C

http模組初始過程

要理解一個核心部分,模組的初始化概括起來就是申請儲存下一級模組配置結構體的空間,並且呼叫相應的回撥生成模組的配置結構體,然後再開始通過ngx_conf_t指定的內容去解析配置檔案,進行配置指令的儲存 1.ngx_http_module_t 所有http模組都是ngx_http_modul

[Android]高效能MMKV資料互動分析-MMKV初始

大家好,我係蒼王。 以下是我這個系列的相關文章,有興趣可以參考一下,可以給個喜歡或者關注我的文章。 [Android]如何做一個崩潰率少於千分之三噶應用app--章節列表 元件化群1已經滿員,進來的可以加群2 763094035 MMKV框架初始化 MMKV.initiali

Lumen開發:lumen原始碼解讀之初始(2)——門面(Facades)與資料庫(db)

緊接上一篇 $app->withFacades();//為應用程式註冊門面。 $app->withEloquent();//為應用程式載入功能強大的庫。 先來看看withFacades() /** * Register the facades

Lumen開發:lumen原始碼解讀之初始(1)——app例項

先來看看入口檔案public/index.php //請求頭 header('Content-Type: application/json; charset=utf-8'); /* |-------------------------------------------------

twemproxy0.4原理分析-系統初始過程原理分析

概述 本文介紹twemproxy的系統初始化過程。該過程包括以下幾個方面的內容: 讀取配置檔案,根據配置檔案初始化資料結構 和後臺伺服器建立連線,形成伺服器連線池 初始化事件處理框架,並設定最開始的事件處理函式 建立twemproxy的監聽socket,

Vue原始碼探究-狀態初始

Vue原始碼探究-狀態初始化 本篇程式碼位於vue/src/core/instance/state.js 繼續隨著核心類的初始化展開探索其他的模組,這一篇來研究一下Vue的狀態初始化。這裡的狀態初始化指的就是在建立例項的時候,在配置物件裡定義的屬性、資料變數、方法等是如何進行初始處理的。由於隨後的資料更新