微信公衆號:Nginx源碼分析
關注可瞭解更多的Nginx
知識。任何問題或建議,請公衆號留言;
關注公衆號,有趣有內涵的文章第一時間送達!nginx
咱們在上一篇文章中詳細的分析了auto/types/sizeof
腳本源碼,本文咱們繼續分析auto/types
目錄下的腳本文件。咱們首先回顧一下nginx
中的大體輔助腳本圖片,以下圖:
web
auto/types/typedef
腳本,
Nginx
的腳本名稱以及變量名稱都是很是的直截了當,咱們徹底能夠見名知意,這是咱們在寫代碼的時候要學習借鑑的地方。從這個腳本的名稱中咱們便可以看到,它的做用就是生成typedef
聲明的。bash
ngx_type
:類型1ngx_types
:類型2微信
判斷ngx_type
和ngx_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_type
和ngx_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_type
和ngx_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源碼分析
)。