Nginx源碼分析之--auto/types/typedef腳本

微信公衆號:Nginx源碼分析
關注可瞭解更多的Nginx知識。任何問題或建議,請公衆號留言;
關注公衆號,有趣有內涵的文章第一時間送達!nginx

回顧

咱們在上一篇文章中詳細的分析了auto/types/sizeof腳本源碼,本文咱們繼續分析auto/types目錄下的腳本文件。咱們首先回顧一下nginx中的大體輔助腳本圖片,以下圖:
web

nginx輔助腳本
nginx輔助腳本

本文講述一下 auto/types/typedef腳本,

auto/types/typedef腳本

Nginx的腳本名稱以及變量名稱都是很是的直截了當,咱們徹底能夠見名知意,這是咱們在寫代碼的時候要學習借鑑的地方。從這個腳本的名稱中咱們便可以看到,它的做用就是生成typedef聲明的。bash

auto/types/sizeof腳本

參數

ngx_type:類型1
ngx_types:類型2微信

功能

判斷ngx_typengx_types是否存在,根據判斷條件生成相應的typedef語句。app

示例

咱們此次先看一下腳本使用的示例,從而全面瞭解一下這個腳本。
auto/unix腳本中,調用了auto/types/typedef腳本,以下:socket

ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef
複製代碼
腳本內容
echo $ngx_n "checking for $ngx_type ...$ngx_c"

cat << END >> $NGX_AUTOCONF_ERR

----------------------------------------
checking for $ngx_type

END

ngx_found=no

for ngx_try in $ngx_type $ngx_types
do

    cat << END > $NGX_AUTOTEST.c

#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
$NGX_INCLUDE_INTTYPES_H

int main() {
    $ngx_try i = 0;
    return 0;
}

END

    ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
              -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"


    eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"

    if [ -x $NGX_AUTOTEST ]; then
        if [ $ngx_try = $ngx_type ]; then
            echo " found"
            ngx_found=yes
        else
            echo ", $ngx_try used"
            ngx_found=$ngx_try
        fi
    fi

    rm -f $NGX_AUTOTEST

    if [ $ngx_found = no ]; then
        echo $ngx_n $ngx_try not found$ngx_c"

        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

    else
        break
    fi
done

if [ $ngx_found = no ]; then
    echo
    echo "$0: error: can not define $ngx_type"

    exit 1
fi

if [ $ngx_found != yes ]; then
    echo "typedef $ngx_found  $ngx_type;"   >> $NGX_AUTO_CONFIG_H
fi
複製代碼
腳本分析

咱們按照示例的調用例子進行腳本分析。函數

1). 首先是向控制檯輸出信息
咱們在前面的文章中分析過ngx_c變量,這裏再也不贅述。
sh echo $ngx_n "checking for $ngx_type ...$ngx_c"
咱們在終端上能夠看到以下內容:
sh checking for uint64_t ... 源碼分析

2).NGX_AUTOCONF_ERR中生成內容。學習

cat << END >> $NGX_AUTOCONF_ERR

----------------------------------------
checking for $ngx_type

END

END
複製代碼

因此,實際上向NGX_AUTOCONF_ERR中寫入的內容是:測試

checking for uint64_t
複製代碼

從前面的文章到如今,咱們能夠看出來,Nginx的每一步都有完善的日誌,這對於監控程序的執行流程以及分析錯誤緣由是很是有幫助的。

3). 生成測試程序

ngx_found=no
複製代碼

這裏首先將ngx_found的內容賦值爲no,這個變量在後面用來表示是否存在咱們要檢測的數據類型。

接着,auto/types/typedef腳本經過一個for循環遍歷傳進來的ngx_typengx_types,每次循環處理過程都是同樣。咱們分析一下這個for循環。
對於每次循環,都會根據當前遍歷到的變量生成一份測試用的c源碼,以下:

    cat << END > $NGX_AUTOTEST.c

#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
$NGX_INCLUDE_INTTYPES_H

int main() {
    $ngx_try i = 0;
    return 0;
}

END
複製代碼

實際對於咱們示例的狀況,第一次循環生成的代碼以下:

#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <inttypes.h>

int main() {
    uint64_t i = 0;
    return 0;
}
複製代碼

這個源文件真的是很簡單,main函數中只有一行實際的代碼。這行代碼的做用很簡單:若是uint64_i這個類型存在的話,那麼這個源文件確定能編譯成功,而且最終生成能夠執行的目標文件。咱們能夠經過檢測最終的目標文件是否能夠被執行來間接的判斷uint64_t類型是否存在。

4). 編譯上面生成的源文件

ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
              -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"


    eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
複製代碼

上面的ngx_test就是一個編譯語句,具體內容以下:

gcc     -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64    -o objs/autotest objs/autotest.c
複製代碼

緊接着的eval語句會執行ngx_test的內容,也就是執行編譯語句,生成能夠執行文件objs/autotest

5). 執行可執行程序

if [ -x $NGX_AUTOTEST ]; then
        if [ $ngx_try = $ngx_type ]; then
        # $ngx_type是傳給for循環的第一個循環參數。因此若是可以執行到這裏,則說明第一個參數$ngx_type表明的類型存在
            echo " found"
            ngx_found=yes
        else
        # 若是執行到這裏,那麼說明$ngx_type表明的變量類型不存在,可是$ngx_types表明的變量類型存在, 這個時候 ngx_found就會被賦值爲$ngx_types類型
            echo ", $ngx_try used"
            ngx_found=$ngx_try
        fi
fi
複製代碼

nginx判斷若是第4步生成的目標文件是是可執行文件-x $NGX_AUTOTEST,那麼執行該目標文件.
這段代碼的詳細分析我已經在代碼裏面進行了註釋。

6).刪除目標文件

rm -f $NGX_AUTOTEST
複製代碼

Nginx會在運行完可執行文件以後就將該文件刪除,因此實際上咱們在Nginx的目錄中是不能看到這些文件的,它們都是臨時文件。

7).根據上面的執行結果進行錯誤輸出

if [ $ngx_found = no ]; then
        echo $ngx_n $ngx_try not found$ngx_c"

        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

    else
    # 若是當前的數據類型存在,那麼就break,再也不進行下面的for循環
        break
fi
複製代碼

若是當前遍歷的變量類型並不存在,會進行日誌輸出。
首先,在控制檯上面輸出unit64_t not found(咱們假設當前檢測的uint64_t類型不存在)。
而後,把生成的檢測數據類型的c源文件以及便一直令保存到NGX_AUTOCONF_ERR文件中,便於進行錯誤分析。

8). 循環結束後的處理
這裏要分三種種狀況,以下:

① ``ngx_typengx_types都不存在。那麼執行下面的腳本:

if [ $ngx_found = no ]; then
    echo
    echo "$0: error: can not define $ngx_type"

    exit 1
fi
複製代碼

這部分腳本會向控制檯輸出一行錯誤信息,告訴nginx不能使用當前的變量類型,而後結束腳本。

ngx_type存在。若是是這種狀況的話,ngx_found的值是yes,這樣的話,auto/types/typedef腳本就直接結束了。

③ ngx_type類型不存在,可是ngx_types存在。這個時候ngx_found的值是ngx_types的值。因此會執行下面的腳本:

if [ $ngx_found != yes ]; then
    echo "typedef $ngx_found  $ngx_type;"   >> $
fi
複製代碼

也就是向NGX_AUTO_CONFIG_H頭文件中生成一個typedef語句。以下:

typedef $ngx_types  $ngx_type;
複製代碼

也便是把ngx_type做爲$ngx_types的別名,這樣程序中就能夠一直使用ngx_type這種類型。
對於本例來講,假設知足第種條件的話,就會生成一個以下的typedef語句:

typedef u_int64_t uint64_t;
複製代碼

到此爲止,咱們已經分析完了auto/types/typedef腳本。

總結

本文詳細的分析了auto/types/sizeof腳本的功能:測試一個c語言數據類型在特定操做系統上的長度,根據長度進行不一樣的操做。
其實咱們經過這幾篇文章能夠發現一個東東,Nginx的許多腳本都是自動生成的,說實話,我之前看的源碼比較少,也沒有關注過這種大型工程的配置文件,真的是一種很是巧妙的方法,咱們能夠多多借鑑。
後面的文章咱們會接着分析nginx的其餘輔助腳本,敬請期待。順便關注個人個公衆號(Nginx源碼分析)。

相關文章
相關標籤/搜索