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

微信公眾號:Nginx源碼分析
關(guān)注可了解更多的Nginx知識。任何問題或建議,請公眾號留言;
關(guān)注公眾號,有趣有內(nèi)涵的文章第一時間送達!

回顧

我們在上一篇文章中詳細的分析了auto/types/sizeof腳本源碼,本文我們繼續(xù)分析auto/types目錄下的腳本文件。我們首先回顧一下nginx中的大致輔助腳本圖片,如下圖:

nginx輔助腳本

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

auto/types/typedef腳本

Nginx的腳本名稱以及變量名稱都是非常的直截了當,我們完全可以見名知意,這是我們在寫代碼的時候要學習借鑒的地方。從這個腳本的名稱中我們即可以看到,它的作用就是生成typedef聲明的。

auto/types/sizeof腳本

參數(shù)

ngx_type:類型1
ngx_types:類型2

功能

判斷ngx_typengx_types是否存在,根據(jù)判斷條件生成相應(yīng)的typedef語句。

示例

我們這次先看一下腳本使用的示例,從而全面了解一下這個腳本。
auto/unix腳本中,調(diào)用了auto/types/typedef腳本,如下:

ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef
腳本內(nèi)容
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
腳本分析

我們按照示例的調(diào)用例子進行腳本分析。

1). 首先是向控制臺輸出信息
我們在前面的文章中分析過ngx_c變量,這里不再贅述。

echo $ngx_n "checking for $ngx_type ...$ngx_c"   

我們在終端上可以看到如下內(nèi)容:

checking for uint64_t ...

2).NGX_AUTOCONF_ERR中生成內(nèi)容。

cat << END >> $NGX_AUTOCONF_ERR

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

END

END

所以,實際上向NGX_AUTOCONF_ERR中寫入的內(nèi)容是:

checking for uint64_t

從前面的文章到現(xiàn)在,我們可以看出來,Nginx的每一步都有完善的日志,這對于監(jiān)控程序的執(zhí)行流程以及分析錯誤原因是非常有幫助的。

3). 生成測試程序

ngx_found=no

這里首先將ngx_found的內(nèi)容賦值為no,這個變量在后面用來表示是否存在我們要檢測的數(shù)據(jù)類型。

接著,auto/types/typedef腳本通過一個for循環(huán)遍歷傳進來的ngx_typengx_types,每次循環(huán)處理過程都是一樣。我們分析一下這個for循環(huán)。
對于每次循環(huán),都會根據(jù)當前遍歷到的變量生成一份測試用的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

實際對于我們示例的情況,第一次循環(huán)生成的代碼如下:

#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函數(shù)中只有一行實際的代碼。這行代碼的作用很簡單:如果uint64_i這個類型存在的話,那么這個源文件肯定能編譯成功,并且最終生成可以執(zhí)行的目標文件。我們可以通過檢測最終的目標文件是否可以被執(zhí)行來間接的判斷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就是一個編譯語句,具體內(nèi)容如下:

gcc     -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64    -o objs/autotest objs/autotest.c

緊接著的eval語句會執(zhí)行ngx_test的內(nèi)容,也就是執(zhí)行編譯語句,生成可以執(zhí)行文件objs/autotest

5). 執(zhí)行可執(zhí)行程序

if [ -x $NGX_AUTOTEST ]; then
        if [ $ngx_try = $ngx_type ]; then
        # $ngx_type是傳給for循環(huán)的第一個循環(huán)參數(shù)。所以如果能夠執(zhí)行到這里,則說明第一個參數(shù)$ngx_type代表的類型存在
            echo " found"
            ngx_found=yes
        else
        # 如果執(zhí)行到這里,那么說明$ngx_type代表的變量類型不存在,但是$ngx_types代表的變量類型存在, 這個時候 ngx_found就會被賦值為$ngx_types類型
            echo ", $ngx_try used"
            ngx_found=$ngx_try
        fi
fi

nginx判斷如果第4步生成的目標文件是是可執(zhí)行文件-x $NGX_AUTOTEST,那么執(zhí)行該目標文件.
這段代碼的詳細分析我已經(jīng)在代碼里面進行了注釋。

6).刪除目標文件

rm -f $NGX_AUTOTEST

Nginx會在運行完可執(zhí)行文件之后就將該文件刪除,所以實際上我們在Nginx的目錄中是不能看到這些文件的,它們都是臨時文件。

7).根據(jù)上面的執(zhí)行結(jié)果進行錯誤輸出

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
    # 如果當前的數(shù)據(jù)類型存在,那么就break,不再進行下面的for循環(huán)
        break
fi

如果當前遍歷的變量類型并不存在,會進行日志輸出。
首先,在控制臺上面輸出unit64_t not found(我們假設(shè)當前檢測的uint64_t類型不存在)。
然后,把生成的檢測數(shù)據(jù)類型的c源文件以及便一直令保存到NGX_AUTOCONF_ERR文件中,便于進行錯誤分析。

8). 循環(huán)結(jié)束后的處理
這里要分三種種情況,如下:

① ``ngx_typengx_types都不存在。那么執(zhí)行下面的腳本:

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

    exit 1
fi

這部分腳本會向控制臺輸出一行錯誤信息,告訴nginx不能使用當前的變量類型,然后結(jié)束腳本。

ngx_type存在。如果是這種情況的話,ngx_found的值是yes,這樣的話,auto/types/typedef腳本就直接結(jié)束了。

③ ngx_type類型不存在,但是ngx_types存在。這個時候ngx_found的值是ngx_types的值。所以會執(zhí)行下面的腳本:

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這種類型。
對于本例來說,假設(shè)滿足第種條件的話,就會生成一個如下的typedef語句:

typedef u_int64_t uint64_t;

到此為止,我們已經(jīng)分析完了auto/types/typedef腳本。

總結(jié)

本文詳細的分析了auto/types/sizeof腳本的功能:測試一個c語言數(shù)據(jù)類型在特定操作系統(tǒng)上的長度,根據(jù)長度進行不同的操作。
其實我們通過這幾篇文章可以發(fā)現(xiàn)一個東東,Nginx的許多腳本都是自動生成的,說實話,我以前看的源碼比較少,也沒有關(guān)注過這種大型工程的配置文件,真的是一種非常巧妙的方法,我們可以多多借鑒。
后面的文章我們會接著分析nginx的其他輔助腳本,敬請期待。順便關(guān)注我的個公眾號(Nginx源碼分析)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容