微信公眾號:Nginx源碼分析
關(guān)注可了解更多的Nginx知識。任何問題或建議,請公眾號留言;
關(guān)注公眾號,有趣有內(nèi)涵的文章第一時間送達!
回顧
我們在上一篇文章中詳細的分析了auto/types/sizeof腳本源碼,本文我們繼續(xù)分析auto/types目錄下的腳本文件。我們首先回顧一下nginx中的大致輔助腳本圖片,如下圖:

本文講述一下
auto/types/typedef腳本,
auto/types/typedef腳本
Nginx的腳本名稱以及變量名稱都是非常的直截了當,我們完全可以見名知意,這是我們在寫代碼的時候要學習借鑒的地方。從這個腳本的名稱中我們即可以看到,它的作用就是生成typedef聲明的。
auto/types/sizeof腳本
參數(shù)
ngx_type:類型1
ngx_types:類型2
功能
判斷ngx_type和ngx_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_type和ngx_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_type和ngx_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源碼分析)。