国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Nginx 源碼分析:從模塊到配置(上)

gotham / 2888人閱讀

摘要:結構體數組,用來表示該模塊可以在配置文件中配置的項目,及其操作指令。

源文件路徑
srccore
gx_conf_file.h
srccore
gx_conf_file.c
主要內容

本篇的主要目的在于分析Nginx的配置功能。由于Nginx的配置基本就是對模塊的配置,因此,在討論配置功能之前,需要先分析Nginx的模塊功能。

對于模塊功能,這里的重點不在于某個模塊的細節,而在于分析Nginx的模塊架構是如何設計的。

類似地,因為對于Nginx的配置文件,沒有資料比官方文檔上說得更明白,所以,這里的重點并不是對配置文件,而是分析Nginx的配置功能是如何設計的。

好了,開始吧。

模塊功能

Nginx的基礎架構是高度模塊化的。可以從多個方面來觀察Nginx的模塊化。

官方文檔首頁的整個下半頁是Nginx自身所有模塊的列表。從這里可以看到Nginx的模塊輪廓。

如果從源碼安裝Nginx,那么首先執行的configure腳本的配置參數里,很大一部分是用來管理是否安裝某個模塊的。當然,Nginx運行必備的模塊是必須安裝的,因此,并不會出現在configure的配置選項里。

Nginx本身由多個基本的模塊構成,其中,核心的部分是一個叫ngx_core_module的模塊。當然,對于一個web服務器,僅僅有一個核心是不夠的,還需要大量的“輔助模塊”。這有點像Linux的設計,一堆外圍設施作為模塊與Linux內核構成整個Linux系統。

很自然的會想到,Nginx的這種模塊化設計是支持第三方插件的。這種設計也大大增加了Nginx的彈性和能力。

模塊的組織和管理

既然Nginx是由許多模塊構成的,那么,如何組織和管理這些模塊是首先要關注的問題。在Nginx中,使用全局數組ngx_modules保存和管理所有Nginx的模塊

如何做到的呢?

首先,Nginx的眾多模塊被分成兩類:必須安裝的模塊可以安裝的模塊

必須安裝的模塊是保證Nginx正常功能的模塊,沒得選擇,這些模塊會出現在ngx_modules里。比如ngx_core_module

可以安裝的模塊通過configure的配置和系統環境,被有選擇的安裝,這些模塊里,被選擇安裝的模塊會出現在ngx_modules數組中。

configure執行結束后,會生成一個objs gx_modules.c的源代碼文件:
文件內容隨configure配置不同而不同,例如:

#include 
#include 

extern ngx_module_t  ngx_core_module;
extern ngx_module_t  ngx_errlog_module;
extern ngx_module_t  ngx_conf_module;
extern ngx_module_t  ngx_events_module;
extern ngx_module_t  ngx_event_core_module;
extern ngx_module_t  ngx_epoll_module;
extern ngx_module_t  ngx_regex_module;
extern ngx_module_t  ngx_http_module;
extern ngx_module_t  ngx_http_core_module;
extern ngx_module_t  ngx_http_log_module;
extern ngx_module_t  ngx_http_upstream_module;
extern ngx_module_t  ngx_http_static_module;
extern ngx_module_t  ngx_http_autoindex_module;
extern ngx_module_t  ngx_http_index_module;

...

ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    &ngx_events_module,
    &ngx_event_core_module,
    &ngx_epoll_module,
    &ngx_regex_module,
    &ngx_http_module,
    &ngx_http_core_module,
    &ngx_http_log_module,
    &ngx_http_upstream_module,
    &ngx_http_static_module,
    &ngx_http_autoindex_module,
    &ngx_http_index_module,
   ...
    NULL
};

由于數組存放的是同一類型的數據。因此,必須有一個模塊基類來抽象的定義所有模塊。這個抽象基類就是ngx_module_t

因此,可以看到ngx_modules數組里存放的是ngx_module_t *類型指針,并且,最后一個一定是空指針NULL

將最后一個元素置為空指針NULL,是為了遍歷數組的時候,標記數組結束,這樣不必在使用時記錄數組大小。

例如:

for (i = 0; ngx_modules[i]; i++) {
    ...
}

使用extern ngx_module_t ngx_core_module;使編譯器在編譯的時候不去處理ngx_core_module,在鏈接階段,再將ngx_core_module鏈接到正確的地址中。

類似地,在源文件core gx_conf_file.h的末尾聲明外部ngx_modules[]

extern ngx_module_t  *ngx_modules[];

由于core gx_conf_file.h會被當作公共頭文件被包含到其他文件中,因此,ngx_modules是一個全局變量

======分割線=======
在編譯階段,objs gx_modules.c文件中的那一堆extern變量及ngx_modules變量都會被初始化。原因在于,這些變量都屬于全局變量,將會被靜態初始化
======分割線=======

這樣,有了全局數組ngx_modules,就可以獲取所有模塊的指針,從而操作所有模塊。對所有模塊的管理和操作也由此展開。

所有模塊的基類 ngx_module_t

所有模塊都是ngx_module_t類型的變量,其定義如下:

struct ngx_module_s {
    ngx_uint_t            ctx_index;
    ngx_uint_t            index;

    ngx_uint_t            spare0;
    ngx_uint_t            spare1;
    ngx_uint_t            spare2;
    ngx_uint_t            spare3;

    ngx_uint_t            version;

    void                 *ctx;
    ngx_command_t        *commands;
    ngx_uint_t            type;

    ngx_int_t           (*init_master)(ngx_log_t *log);

    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);

    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
    void                (*exit_thread)(ngx_cycle_t *cycle);
    void                (*exit_process)(ngx_cycle_t *cycle);

    void                (*exit_master)(ngx_cycle_t *cycle);

    uintptr_t             spare_hook0;
    uintptr_t             spare_hook1;
    uintptr_t             spare_hook2;
    uintptr_t             spare_hook3;
    uintptr_t             spare_hook4;
    uintptr_t             spare_hook5;
    uintptr_t             spare_hook6;
    uintptr_t             spare_hook7;
};

各成員變量含義如下

1. type

type變量是指模塊的類型。Nginx中模塊的類型定義如下:

#define NGX_CORE_MODULE      0x45524F43  /* "CORE" */
#define NGX_CONF_MODULE      0x464E4F43  /* "CONF" */
#define NGX_EVENT_MODULE     0x544E5645  /* "EVNT" */
#define NGX_HTTP_MODULE      0x50545448  /* "HTTP" */
#define NGX_MAIL_MODULE      0x4C49414D  /* "MAIL" */

也就是說,Nginx共有5中模塊類型CORFCONFEVNTHTTPMAIL

2. index

index變量是指,該模塊在ngx_modules數組中的次序,或者說下標。該變量在Nginx執行初始化的時候被初始化,初始化代碼位于core ginx.cmain函數中:

    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = ngx_max_module++;
    }

3. ctx_index

ctx_index是指,在ngx_modules數組中,該模塊在相同類型的模塊中的次序。

例如,ngx_modules數組中有多個類型為NGX_EVENT_MODULE的模塊,那么其中一個模塊的ctx_index初始化如下:

// 源碼文件event
gx_event.c
    ngx_event_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
            continue;
        }
        ngx_modules[i]->ctx_index = ngx_event_max_module++;
    }

4. ctx

ctxvoid *指針型變量,這是指向與模塊相關的上下文

這里先解釋一下什么叫與模塊相關的上下文

上下文這個概念一般可以理解為運行環境,那么與模塊相關的上下文就是指模塊運行環境。換句話說,就是一些參數的配置信息。因為配置一般意味著設置,而設置的對象就是模塊的運行環境。比如,ngx_core_modules運行時的usergroup,就屬于運行環境,同時,也屬于配置項。

由于模塊的參數一般比較多,正確設置參數的配置需要很多操作。所以,上下文其實也意味著一組操作,這組操作的目的在于根據配置,正確設置模塊的參數信息。同時,這也意味著,不同的模塊,這組操作是不同的,因此,這里需要將ctx設置為void *指針,來進行泛型的操作。

ngx_core_module為例,其ctx指向的上下文是這個樣子的:

static ngx_core_module_t  ngx_core_module_ctx = {
    ngx_string("core"),
    ngx_core_module_create_conf,
    ngx_core_module_init_conf
};

其中ngx_core_module_t的定義如下:

typedef struct {
    ngx_str_t             name;
    void               *(*create_conf)(ngx_cycle_t *cycle);
    char               *(*init_conf)(ngx_cycle_t *cycle, void *conf);
} ngx_core_module_t;

而這組操作中的ngx_core_module_init_conf函數中,初始化了一個ngx_core_conf_t的結構體。

因此,可知,void *ctx指向了一組操作,這組操作的目的在于初始化一個與模塊配置信息相關的結構體
這里涉及到了三個結構體:

ngx_module_t ngx_core_module:用來表示模塊本身,保存在ngx_modules數組中;

ngx_core_conf_t core_conf:用來保存對該模塊的配置信息;

ngx_core_module_t ngx_core_module_ctx:用來初始化ngx_core_conf_t中的成員變量;

6. commands

commands是ngx_command_t數組,表示一組配置文件中的可配項(指令)。

例如,在配置文件nginx.confworker_processes 1;對應commands數組中的一項,該項的定義如下,類型為ngx_command_t

{ ngx_string("worker_processes"),
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
      ngx_set_worker_processes,
      0,
      0,
      NULL }

其中ngx_command_t定義如下:

struct ngx_command_s {
    ngx_str_t             name;
    ngx_uint_t            type;
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;
    ngx_uint_t            offset;
    void                 *post;
};

所以,commands的含義在于該模塊的配置項在配置文件中的指令

ngx_module_t 總結

到這里,一個完整的模塊所需的各個部分逐漸顯露出來了:

ngx_module_t結構體,用來表示模塊的定義,被放入ngx_modules數組中。

ngx__conf_t結構體,用來表示模塊的配置項,這個結構體隨模塊的不同而不同,通過上下文操作及commands中定義的指令,由配置文件確定其成員值。

ngx__module_t結構體,表示一組用來初始化ngx__conf_t結構體的操作。在Nginx初始化時被調用,初始化ngx__conf_t結構體。

ngx_command_t結構體數組,用來表示該模塊可以在配置文件中配置的項目,及其操作指令。在Nginx初始化解析配置文件后,調用ngx_command_t中的函數set初始化ngx__conf_t結構體。

總結

Nginx中,一個模塊運行所需的各種配置參數被封裝成了ngx__conf_t結構體。

這個結構體內成員變量的初始化被分成了兩部分:

模塊相關的上下文ngx__module_t:即定義了一組初始化操作,用來將該結構體內的各成員初始化。

配置文件相關指令ngx_command_t:即規定了配置文件中可以使用的指令及其對應的操作函數。

而模塊本身被封裝成了ngx_module_t類型結構體,被用來供Nginx統一管理和使用。

模塊和配置的聯系非常緊密,因此,這里僅僅先大略的分析一下模塊功能的整體框架,下一篇中,將在本篇的基礎上分析Nginx的配置功能。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/39155.html

相關文章

  • Nginx 源碼分析模塊配置(下)

    摘要:每個模塊由以下幾部分構成結構體代表模塊本身,其指針被放入數組中。結構體用來表示模塊的配置內容,其中部分成員可以通過配置文件進行配置。調用該中的函數,該函數最終初始化模塊對應的結構體,完成配置。因此,分析源碼中的配置指令,就是分析結構體。 本篇的上篇 Nginx 源碼分析:從模塊到配置(上),建議閱讀本篇前先閱讀上篇。 關于模塊 Nginx的架構高度模塊化。每個模塊各司其職,組合在一...

    Chao 評論0 收藏0
  • Nginx源碼分析Nginx配置文件解析(一)

    摘要:本文將從源碼從此深入分析配置文件的解析,配置存儲,與配置查找。在學習配置文件的解析過程之前,需要先了解一下模塊與指令的一些基本知識。 運營研發團隊 李樂 配置文件是nginx的基礎,對于學習nginx源碼甚至開發nginx模塊的同學來說更是必須深究。本文將從源碼從此深入分析nginx配置文件的解析,配置存儲,與配置查找。 看本文之前讀者可以先思考兩個問題: 1.nginx源碼中隨處可以...

    JasonZhang 評論0 收藏0
  • Nginx源碼分析Nginx的listen處理流程分析

    摘要:四監聽套接字的使用假設此處我們使用作為事件處理模塊在增加事件時用戶可以使用中的字段當事件發生時該字段也會帶回。在創建監聽套接字時將結構分為級監聽套接字地址各級都是一對多的關系。 施洪寶 一. 基礎 nginx源碼采用1.15.5 后續部分僅討論http中的listen配置解析以及優化流程 1.1 概述 假設nginx http模塊的配置如下 http{ server { ...

    yuanzhanghu 評論0 收藏0
  • Nginx 源碼分析:ngx_hash_t(

    摘要:現在使用的各種哈希函數基本上只能保證較小概率出現兩個不同的其相同的情況。而出現兩個值對應的相同的情況,稱為哈希沖突。中的哈希表需要指出的是,中自造的哈希表屬于內部使用的數據結構,因此,并不是一個通用的哈希表。 源文件路徑 版本:1.8.0 csrccoreNgx_hash.h srccoreNgx_hash.c 關于hash表 Nginx實現的hash表和常見的hash表大體...

    waruqi 評論0 收藏0

發表評論

0條評論

gotham

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<