nginx架構詳解

.
├── auto            自動檢測系統環境以及編譯相關的腳本
│   ├── cc          關於編譯器相關的編譯選項的檢測腳本
│   ├── lib         nginx編譯所須要的一些庫的檢測腳本
│   ├── os          與平臺相關的一些系統參數與系統調用相關的檢測
│   └── types       與數據類型相關的一些輔助腳本
├── conf            存放默認配置文件,在make install後,會拷貝到安裝目錄中去
├── contrib         存放一些實用工具,如geo配置生成工具(geo2nginx.pl)
├── html            存放默認的網頁文件,在make install後,會拷貝到安裝目錄中去
├── man             nginx的man手冊
└── src             存放nginx的源代碼
    ├── core        nginx的核心源代碼,包括經常使用數據結構的定義,以及nginx初始化運行的核心代碼如main函數
    ├── event       對系統事件處理機制的封裝,以及定時器的實現相關代碼
    │   └── modules 不一樣事件處理方式的模塊化,如select、poll、epoll、kqueue等
    ├── http        nginx做爲http服務器相關的代碼
    │   └── modules 包含http的各類功能模塊
    ├── mail        nginx做爲郵件代理服務器相關的代碼
    ├── misc        一些輔助代碼,測試c++頭的兼容性,以及對google_perftools的支持
    └── os          主要是對各類不一樣體系統結構所提供的系統函數的封裝,對外提供統一的系統調用接口

nginx的configure原理(100%)

nginx的編譯旅程將從configure開始,configure腳本將根據咱們輸入的選項、系統環境參與來生成所需的文件(包含源文件與Makefile文件)。configure會調用一系列auto腳原本實現編譯環境的初始化。html

auto腳本

auto腳本由一系列腳本組成,他們有一些是實現一些通用功能由其它腳原本調用(如have),有一些則是完成一些特定的功能(如option)。腳本之間的主要執行順序及調用關係以下圖所示(由上到下,表示主流程的執行):python


接下來,咱們結合代碼來分析下configure的原理:nginx

  1. 初始化
. auto/options
. auto/init
. auto/sources

這是configure源碼開始執行的前三行,依次交由auto目錄下面的option、init、sources來處理。c++

  1. auto/options主是處理用戶輸入的configure選項,以及輸出幫助信息等。讀者能夠結合nginx的源碼來閱讀本章內容。因爲篇幅關係,這裏大體列出此文件的結構:
##1. 設置選項對應的shell變量以及他們的初始值
help=no
NGX_PREFIX=
NGX_SBIN_PATH=
NGX_CONF_PREFIX=
NGX_CONF_PATH=
NGX_ERROR_LOG_PATH=
NGX_PID_PATH=
NGX_LOCK_PATH=
NGX_USER=
NGX_GROUP=

...


## 2, 處理每個選項值,並設置到對應的全局變量中
for option
do
    opt="$opt `echo $option | sed -e \"s/\(--[^=]*=\)\(.* .*\)/\1'\2'/\"`"

    # 獲得此選項的value部分
    case "$option" in
        -*=*) value=`echo "$option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
            *) value="" ;;
    esac

    # 根據option內容進行匹配,並設置相應的選項
    case "$option" in
        --help)                          help=yes                   ;;
        --prefix=)                       NGX_PREFIX="!"             ;;
        --prefix=*)                      NGX_PREFIX="$value"        ;;
        --sbin-path=*)                   NGX_SBIN_PATH="$value"     ;;
        --conf-path=*)                   NGX_CONF_PATH="$value"     ;;
        --error-log-path=*)              NGX_ERROR_LOG_PATH="$value";;
        --pid-path=*)                    NGX_PID_PATH="$value"      ;;
        --lock-path=*)                   NGX_LOCK_PATH="$value"     ;;
        --user=*)                        NGX_USER="$value"          ;;
        --group=*)                       NGX_GROUP="$value"         ;;

        ...

        *)
            # 沒有找到的對應選項
            echo "$0: error: invalid option \"$option\""
            exit 1
        ;;
    esac
done

## 3. 對選項進行處理

# 若是有--help,則輸出幫助信息
if [ $help = yes ]; then

    cat << END

        --help                             print this message

        --prefix=PATH                      set installation prefix
        --sbin-path=PATH                   set nginx binary pathname
        --conf-path=PATH                   set nginx.conf pathname
        --error-log-path=PATH              set error log pathname
        --pid-path=PATH                    set nginx.pid pathname
        --lock-path=PATH                   set nginx.lock pathname

        --user=USER                        set non-privileged user for
        worker processes
        --group=GROUP                      set non-privileged group for
                                 worker processes
END

    exit 1
fi

# 默認文件路徑
NGX_CONF_PATH=${NGX_CONF_PATH:-conf/nginx.conf}
NGX_CONF_PREFIX=`dirname $NGX_CONF_PATH`
NGX_PID_PATH=${NGX_PID_PATH:-logs/nginx.pid}
NGX_LOCK_PATH=${NGX_LOCK_PATH:-logs/nginx.lock}

...

上面的代碼中,咱們選用了文件中的部分代碼進行了說明。你們可結合源碼再進行分析。auto/options的目的主要是處理用戶選項,並由選項生成一些全局變量的值,這些值在其它文件中會用到。該文件也會輸出configure的幫助信息。shell

  1. auto/init

該文件的目錄在於初始化一些臨時文件的路徑,檢查echo的兼容性,並建立Makefile。服務器

# 生成最終執行編譯的makefile文件路徑
NGX_MAKEFILE=$NGX_OBJS/Makefile
# 動態生成nginx模塊列表的路徑,因爲nginx的的一些模塊是能夠選擇編譯的,並且能夠添加本身的模塊,因此模塊列表是動態生成的
NGX_MODULES_C=$NGX_OBJS/ngx_modules.c

NGX_AUTO_HEADERS_H=$NGX_OBJS/ngx_auto_headers.h
NGX_AUTO_CONFIG_H=$NGX_OBJS/ngx_auto_config.h

# 自動測試目錄與日誌輸出文件
NGX_AUTOTEST=$NGX_OBJS/autotest
# 若是configure出錯,可用來查找出錯的緣由
NGX_AUTOCONF_ERR=$NGX_OBJS/autoconf.err

NGX_ERR=$NGX_OBJS/autoconf.err
MAKEFILE=$NGX_OBJS/Makefile


NGX_PCH=
NGX_USE_PCH=


# 檢查echo是否支持-n或\c

# check the echo's "-n" option and "\c" capability

if echo "test\c" | grep c >/dev/null; then

    # 不支持-c的方式,檢查是否支持-n的方式

    if echo -n test | grep n >/dev/null; then
        ngx_n=
        ngx_c=

    else
        ngx_n=-n
        ngx_c=
    fi

else
    ngx_n=
    ngx_c='\c'
fi

# 建立最初始的makefile文件
# default表示目前編譯對象
# clean表示執行clean工做時,須要刪除makefile文件以及objs目錄
# 整個過程當中只會生成makefile文件以及objs目錄,其它全部臨時文件都在objs目錄之下,因此執行clean後,整個目錄還原到初始狀態
# 要再次執行編譯,須要從新執行configure命令

# create Makefile

cat << END > Makefile

default:    build

clean:
    rm -rf Makefile $NGX_OBJS
END
  1. auto/sources

該文件從文件名中就能夠看出,它的主要功能是跟源文件相關的。它的主要做用是定義不一樣功能或系統所須要的文件的變量。根據功能,分爲CORE/REGEX/EVENT/UNIX/FREEBSD/HTTP等。每個功能將會由四個變量組成,」_MODULES」表示此功能相關的模塊,最終會輸出到ngx_modules.c文件中,即動態生成須要編譯到nginx中的模塊;」INCS」表示此功能依賴的源碼目錄,查找頭文件的時候會用到,在編譯選項中,會出如今」-I」中;」DEPS」顯示指明在Makefile中須要依賴的文件名,即編譯時,須要檢查這些文件的更新時間;」SRCS」表示須要此功能編譯須要的源文件。數據結構

拿core來講:memcached

CORE_MODULES="ngx_core_module ngx_errlog_module ngx_conf_module ngx_emp_server_module ngx_emp_server_core_module" CORE_INCS="src/core" CORE_DEPS="src/core/nginx.h \  src/core/ngx_config.h \  src/core/ngx_core.h \  src/core/ngx_log.h \  src/core/ngx_palloc.h \  src/core/ngx_array.h \  src/core/ngx_list.h \  src/core/ngx_hash.h \  src/core/ngx_buf.h \  src/core/ngx_queue.h \  src/core/ngx_string.h \  src/core/ngx_parse.h \  src/core/ngx_inet.h \  src/core/ngx_file.h \  src/core/ngx_crc.h \  src/core/ngx_crc32.h \  src/core/ngx_murmurhash.h \  src/core/ngx_md5.h \  src/core/ngx_sha1.h \  src/core/ngx_rbtree.h \  src/core/ngx_radix_tree.h \  src/core/ngx_slab.h \  src/core/ngx_times.h \  src/core/ngx_shmtx.h \  src/core/ngx_connection.h \  src/core/ngx_cycle.h \  src/core/ngx_conf_file.h \  src/core/ngx_resolver.h \  src/core/ngx_open_file_cache.h \  src/core/nginx_emp_server.h \  src/core/emp_server.h \  src/core/task_thread.h \  src/core/standard.h \  src/core/dprint.h \  src/core/ngx_crypt.h" CORE_SRCS="src/core/nginx.c \  src/core/ngx_log.c \  src/core/ngx_palloc.c \  src/core/ngx_array.c \  src/core/ngx_list.c \  src/core/ngx_hash.c \  src/core/ngx_buf.c \  src/core/ngx_queue.c \  src/core/ngx_output_chain.c \  src/core/ngx_string.c \  src/core/ngx_parse.c \  src/core/ngx_inet.c \  src/core/ngx_file.c \  src/core/ngx_crc32.c \  src/core/ngx_murmurhash.c \  src/core/ngx_md5.c \  src/core/ngx_rbtree.c \  src/core/ngx_radix_tree.c \  src/core/ngx_slab.c \  src/core/ngx_times.c \  src/core/ngx_shmtx.c \  src/core/ngx_connection.c \  src/core/ngx_cycle.c \  src/core/ngx_spinlock.c \  src/core/ngx_cpuinfo.c \  src/core/ngx_conf_file.c \  src/core/ngx_resolver.c \  src/core/ngx_open_file_cache.c \  src/core/nginx_emp_server.c \  src/core/emp_server.c \  src/core/standard.c \  src/core/task_thread.c \  src/core/dprint.c \  src/core/ngx_crypt.c" 

若是咱們本身寫一個第三方模塊,咱們可能會引用到這些變量的值,或對這些變量進行修改,好比添加咱們本身的模塊,或添加本身的一個頭文件查找目錄(在第三方模塊的config中),在後面,咱們會看到它是如何加框第三方模塊的。 在繼續分析執行流程以前,咱們先介紹一些工具腳本。模塊化

  1. auto/have
cat << END >> $NGX_AUTO_CONFIG_H

#ifndef $have
#define $have  1
#endif

END

從代碼中,咱們能夠看到,這個工具的做用是,將$have變量的值,宏定義爲1,並輸出到auto_config文件中。一般咱們經過這個工具來控制是否打開某個特性。這個工具在使用前,須要先定義宏的名稱 ,即$have變量。函數

  1. 再回到configure文件中來:
# NGX_DEBUG是在auto/options文件中處理的,若是有--with-debug選項,則其值是YES
if [ $NGX_DEBUG = YES ]; then
    # 當有debug選項時,會定義NGX_DEBUG宏
    have=NGX_DEBUG . auto/have
fi

這段代碼中,能夠看出,configure是如何定義一個特性的:經過宏定義,輸出到config頭文件中,而後在程序中能夠判斷這個宏是否有定義,來實現不一樣的特性。

configure文件中繼續向下:

# 編譯器選項
. auto/cc/conf

# 頭文件支持宏定義
if [ "$NGX_PLATFORM" != win32 ]; then
    . auto/headers
fi

# 操做系統相關的配置的檢測
. auto/os/conf

# unix體系下的通用配置檢測
if [ "$NGX_PLATFORM" != win32 ]; then
    . auto/unix
fi

configure會依次調用其它幾個文件,來進行環境的檢測,包括編譯器、操做系統相關。

  1. auto/feature

nginx的configure會自動檢測不一樣平臺的特性,神奇之處就是auto/feature的實現,在繼續向下分析以前,咱們先來看看這個工具的實現原理。此工具的核心思想是,輸出一小段表明性c程序,而後設置好編譯選項,再進行編譯鏈接運行,再對結果進行分析。例如,若是想檢測某個庫是否存在,就在小段c程序裏面調用庫裏面的某個函數,再進行編譯連接,若是出錯,則表示庫的環境不正常,若是編譯成功,且運行正常,則庫的環境檢測正常。咱們在寫nginx第三方模塊時,也常使用此工具來進行環境的檢測,因此,此工具的做用貫穿整個configure過程。

先看一小段使用例子:

ngx_feature="poll()"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <poll.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int  n; struct pollfd  pl;
                  pl.fd = 0;
                  pl.events = 0;
                  pl.revents = 0;
                  n = poll(&pl, 1, 0);
                  if (n == -1) return 1"
. auto/feature

if [ $ngx_found = no ]; then
    # 若是沒有找到poll,就設置變量的值
    EVENT_POLL=NONE
fi

這段代碼在auto/unix裏面實現,用來檢測當前操做系統是否支持poll函數調用。在調用auto/feature以前,須要先設置幾個輸入參數變量的值,而後結果會存在$ngx_found變量裏面, 並輸出宏定義以表示支持此特性:

$ngx_feature      特性名稱
$ngx_feature_name 特性的宏定義名稱,若是特性測試成功,則會定義該宏定義
$ngx_feature_path 編譯時要查找頭文件目錄
$ngx_feature_test 要執行的測試代碼
$ngx_feature_incs 在代碼中要include的頭文件
$ngx_feature_libs 編譯時須要link的庫文件選項
$ngx_feature_run  編譯成功後,對二進制文件須要作的動做,能夠是yes value bug 其它

#ngx_found 若是找到,並測試成功,其值爲yes,不然其值爲no

看看ngx_feature的關鍵代碼:

# 初始化輸出結果爲no
ngx_found=no

#將特性名稱小寫轉換成大寫
if test -n "$ngx_feature_name"; then
    # 小寫轉大寫
    ngx_have_feature=`echo $ngx_feature_name \
                   | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
fi

# 將全部include目錄轉換成編譯選項
if test -n "$ngx_feature_path"; then
    for ngx_temp in $ngx_feature_path; do
        ngx_feature_inc_path="$ngx_feature_inc_path -I $ngx_temp"
    done
fi


# 生成臨時的小段c程序代碼。
# $ngx_feature_incs變量是程序須要include的頭文件
# $ngx_feature_test是測試代碼
cat << END > $NGX_AUTOTEST.c

#include <sys/types.h>
$NGX_INCLUDE_UNISTD_H
$ngx_feature_incs

int main() {
    $ngx_feature_test;
    return 0;
}

END

# 編譯命令
# 編譯以後的目標文件是 $NGX_AUTOTEST,後面會判斷這個文件是否存在來判斷是否編譯成功
ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
      -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"

# 執行編譯過程
# 編譯成功後,會生成$NGX_AUTOTEST命名的文件
eval "/bin/sh -c \"$ngx_test\" >> $NGX_AUTOCONF_ERR 2>&1"

# 若是文件存在,則編譯成功
if [ -x $NGX_AUTOTEST ]; then

    case "$ngx_feature_run" in

        # 須要運行來判斷是否支持特性
        # 測試程序可否正常執行(即程序退出後的狀態碼是不是0),若是正常退出,則特性測試成功,設置ngx_found爲yes,並添加名爲ngx_feature_name的宏定義,宏的值爲1
        yes)
            # 若是程序正常退出,退出碼爲0,則程序執行成功,咱們能夠在測試代碼裏面手動返回非0來表示程序出錯
            # /bin/sh is used to intercept "Killed" or "Abort trap" messages
            if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
                echo " found"
                ngx_found=yes

                # 添加宏定義,宏的值爲1
                if test -n "$ngx_feature_name"; then
                    have=$ngx_have_feature . auto/have
                fi

            else
                echo " found but is not working"
            fi
        ;;

        # 須要運行程序來判斷是否支持特性,若是支持,將程序標準輸出的結果做爲宏的值
        value)
        # /bin/sh is used to intercept "Killed" or "Abort trap" messages
        if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
            echo " found"
            ngx_found=yes

            # 與yes不同的是,value會將程序從標準輸出裏面打印出來的值,設置爲ngx_feature_name宏變量的值
            # 在此種狀況下,程序須要設置ngx_feature_name變量名
            cat << END >> $NGX_AUTO_CONFIG_H

#ifndef $ngx_feature_name
#define $ngx_feature_name  `$NGX_AUTOTEST`
#endif

END
            else
                echo " found but is not working"
            fi
        ;;

        # 與yes正好相反
        bug)
            # /bin/sh is used to intercept "Killed" or "Abort trap" messages
            if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
                echo " not found"

            else
                echo " found"
                ngx_found=yes

                if test -n "$ngx_feature_name"; then
                    have=$ngx_have_feature . auto/have
                fi
            fi
        ;;

        # 不須要運行程序,最後定義宏變量
        *)
            echo " found"
            ngx_found=yes

            if test -n "$ngx_feature_name"; then
                have=$ngx_have_feature . auto/have
            fi
        ;;

    esac
else
    # 編譯失敗
    echo " not found"

    # 編譯失敗,會保存信息到日誌文件中
    echo "----------"    >> $NGX_AUTOCONF_ERR
    # 保留編譯文件的內容
    cat $NGX_AUTOTEST.c  >> $NGX_AUTOCONF_ERR
    echo "----------"    >> $NGX_AUTOCONF_ERR
    # 保留編譯文件的選項
    echo $ngx_test       >> $NGX_AUTOCONF_ERR
    echo "----------"    >> $NGX_AUTOCONF_ERR
fi

# 最後刪除生成的臨時文件
rm $NGX_AUTOTEST*
  1. auto/cc/conf

在瞭解了工具auto/feature後,繼續咱們的主流程,auto/cc/conf的代碼就很好理解了,這一步主要是檢測編譯器,並設置編譯器相關的選項。它先調用auto/cc/name來獲得編譯器的名稱,而後根據編譯器選擇執行不一樣的編譯器相關的文件如gcc執行auto/cc/gcc來設置編譯器相關的一些選項。

  1. auto/include

這個工具用來檢測是頭文件是否支持。須要檢測的頭文件放在$ngx_include裏面,若是支持,則$ngx_found變量的值爲yes,而且會產生NGX_HAVE_{ngx_include}的宏定義。

  1. auto/headers

生成頭文件的宏定義。生成的定義放在objs/ngx_auto_headers.h裏面:

#ifndef NGX_HAVE_UNISTD_H #define NGX_HAVE_UNISTD_H 1 #endif #ifndef NGX_HAVE_INTTYPES_H #define NGX_HAVE_INTTYPES_H 1 #endif #ifndef NGX_HAVE_LIMITS_H #define NGX_HAVE_LIMITS_H 1 #endif #ifndef NGX_HAVE_SYS_FILIO_H #define NGX_HAVE_SYS_FILIO_H 1 #endif #ifndef NGX_HAVE_SYS_PARAM_H #define NGX_HAVE_SYS_PARAM_H 1 #endif 
  1. auto/os/conf

針對不一樣的操做系統平臺特性的檢測,並針對不一樣的操做系統,設置不一樣的CORE_INCS、CORE_DEPS、CORE_SRCS變量。nginx跨平臺的支持就是在這個地方體現出來的。

  1. auto/unix

針對unix體系的通用配置或系統調用的檢測,如poll等事件處理系統調用的檢測等。

  1. 回到configure裏面
# 生成模塊列表
. auto/modules
# 配置庫的依賴
. auto/lib/conf
  1. auto/modules

該腳本根據不一樣的條件,輸出不一樣的模塊列表,最後輸出的模塊列表的文件在objs/ngx_modules.c:

#include <ngx_config.h>
#include <ngx_core.h>


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_emp_server_module;

...


ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    &ngx_emp_server_module,
    ...
    NULL
};

這個文件會決定全部模塊的順序,這會直接影響到最後的功能,下一小節咱們將討論模塊間的順序。這個文件會加載咱們的第三方模塊,這也是咱們值得關注的地方:

if test -n "$NGX_ADDONS"; then

    echo configuring additional modules

    for ngx_addon_dir in $NGX_ADDONS
    do
        echo "adding module in $ngx_addon_dir"

        if test -f $ngx_addon_dir/config; then
            # 執行第三方模塊的配置
            . $ngx_addon_dir/config

            echo " + $ngx_addon_name was configured"

        else
            echo "$0: error: no $ngx_addon_dir/config was found"
            exit 1
        fi
    done
fi

這段代碼比較簡單,確實現了nginx很強大的擴展性,加載第三方模塊。$ngx_addon_dir變量是在configure執行時,命令行參數–add-module加入的,它是一個目錄列表,每個目錄,表示一個第三方模塊。從代碼中,咱們能夠看到,它就是針對每個第三方模塊執行其目錄下的config文件。因而咱們能夠在config文件裏面執行咱們本身的檢測邏輯,好比檢測庫依賴,添加編譯選項等。

  1. auto/lib/conf

該文件會針對nginx編譯所須要的基礎庫的檢測,好比rewrite模塊須要的PCRE庫的檢測支持。

  1. configure接下來定義一些宏常量,主要是是文件路徑方面的:
case ".$NGX_PREFIX" in
    .)
        NGX_PREFIX=${NGX_PREFIX:-/usr/local/nginx}
        have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define
    ;;

    .!)
        NGX_PREFIX=
    ;;

    *)
        have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define
    ;;
esac

if [ ".$NGX_CONF_PREFIX" != "." ]; then
    have=NGX_CONF_PREFIX value="\"$NGX_CONF_PREFIX/\"" . auto/define
fi

have=NGX_SBIN_PATH value="\"$NGX_SBIN_PATH\"" . auto/define
have=NGX_CONF_PATH value="\"$NGX_CONF_PATH\"" . auto/define
have=NGX_PID_PATH value="\"$NGX_PID_PATH\"" . auto/define
have=NGX_LOCK_PATH value="\"$NGX_LOCK_PATH\"" . auto/define
have=NGX_ERROR_LOG_PATH value="\"$NGX_ERROR_LOG_PATH\"" . auto/define

have=NGX_HTTP_LOG_PATH value="\"$NGX_HTTP_LOG_PATH\"" . auto/define
have=NGX_HTTP_CLIENT_TEMP_PATH value="\"$NGX_HTTP_CLIENT_TEMP_PATH\""
. auto/define
have=NGX_HTTP_PROXY_TEMP_PATH value="\"$NGX_HTTP_PROXY_TEMP_PATH\""
. auto/define
have=NGX_HTTP_FASTCGI_TEMP_PATH value="\"$NGX_HTTP_FASTCGI_TEMP_PATH\""
. auto/define
have=NGX_HTTP_UWSGI_TEMP_PATH value="\"$NGX_HTTP_UWSGI_TEMP_PATH\""
. auto/define
have=NGX_HTTP_SCGI_TEMP_PATH value="\"$NGX_HTTP_SCGI_TEMP_PATH\""
. auto/define
  1. configure最後的工做,生成編譯安裝的makefile
# 生成objs/makefile文件
. auto/make

# 生成關於庫的編譯選項到makefile文件
. auto/lib/make
# 生成與安裝相關的makefile文件內容,並生成最外層的makefile文件
. auto/install

# STUB
. auto/stubs

have=NGX_USER value="\"$NGX_USER\"" . auto/define
have=NGX_GROUP value="\"$NGX_GROUP\"" . auto/define

# 編譯的最後階段,彙總信息
. auto/summary

模塊編譯順序

上一節中,提到過,nginx模塊的順序很重要,會直接影響到程序的功能。並且,nginx和部分模塊,也有着本身特定的順序要求,好比ngx_http_write_filter_module模塊必定要在filter模塊的最後一步執行。想查看模塊的執行順序,能夠在objs/ngx_modules.c這個文件中找到,這個文件在configure以後生成,上一節中,咱們看過這個文件裏面的內容。

下面是一個ngx_modules.c文件的示例:

ngx_module_t *ngx_modules[] = {
    // 全局core模塊
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    &ngx_emp_server_module,
    &ngx_emp_server_core_module,

    // event模塊
    &ngx_events_module,
    &ngx_event_core_module,
    &ngx_kqueue_module,

    // 正則模塊
    &ngx_regex_module,

    // http模塊
    &ngx_http_module,
    &ngx_http_core_module,
    &ngx_http_log_module,
    &ngx_http_upstream_module,

    // http handler模塊
    &ngx_http_static_module,
    &ngx_http_autoindex_module,
    &ngx_http_index_module,
    &ngx_http_auth_basic_module,
    &ngx_http_access_module,
    &ngx_http_limit_conn_module,
    &ngx_http_limit_req_module,
    &ngx_http_geo_module,
    &ngx_http_map_module,
    &ngx_http_split_clients_module,
    &ngx_http_referer_module,
    &ngx_http_rewrite_module,
    &ngx_http_proxy_module,
    &ngx_http_fastcgi_module,
    &ngx_http_uwsgi_module,
    &ngx_http_scgi_module,
    &ngx_http_memcached_module,
    &ngx_http_empty_gif_module,
    &ngx_http_browser_module,
    &ngx_http_upstream_ip_hash_module,
    &ngx_http_upstream_keepalive_module,
    //此處是第三方handler模塊

    // http filter模塊
    &ngx_http_write_filter_module,
    &ngx_http_header_filter_module,
    &ngx_http_chunked_filter_module,
    &ngx_http_range_header_filter_module,
    &ngx_http_gzip_filter_module,
    &ngx_http_postpone_filter_module,
    &ngx_http_ssi_filter_module,
    &ngx_http_charset_filter_module,
    &ngx_http_userid_filter_module,
    &ngx_http_headers_filter_module,
    // 第三方filter模塊
    &ngx_http_copy_filter_module,
    &ngx_http_range_body_filter_module,
    &ngx_http_not_modified_filter_module,
    NULL
};

http handler模塊與http filter模塊的順序很重要,這裏咱們主要關注一下這兩類模塊。

http handler模塊,在後面的章節裏面會講到多階段請求的處理鏈。對於content phase以前的handler,同一個階段的handler,模塊是順序執行的。好比上面的示例代碼中,ngx_http_auth_basic_module與ngx_http_access_module這兩個模塊都是在access phase階段,因爲ngx_http_auth_basic_module在前面,因此會先執行。因爲content phase只會有一個執行,因此不存在順序問題。另外,咱們加載的第三方handler模塊永遠是在最後執行。

http filter模塊,filter模塊會將全部的filter handler排成一個倒序鏈,因此在最前面的最後執行。上面的例子中,&ngx_http_write_filter_module最後執行,ngx_http_not_modified_filter_module最早執行。注意,咱們加載的第三方filter模塊是在copy_filter模塊以後,headers_filter模塊以前執行。

相關文章
相關標籤/搜索