微信公衆號:Nginx源碼分析
關注可瞭解更多的Nginx
知識。任何問題或建議,請公衆號留言;
關注公衆號,有趣有內涵的文章第一時間送達!linux
咱們在上一篇文章中分析了和編譯器相關的腳本。若是你們不明白的話也不要緊,那部分代碼對於咱們分析nginx
源碼沒有影響。咱們分析的目的也是讓你們看到了一個完整的項目是如何實現各類自動化配置選擇的。nginx
我將在本文中分析nginx
是如何發現
當前的宿主操做系統,以及對特定操做系統進行初始化的過程。
web
咱們首先看一下nginx
是如何經過腳原本肯定當前運行的操做系統版本。
這裏面有一個參數是很重要的,NGX_PLATFORM
,這個參數保存了當前宿主的操做系統,咱們看一下它是如何被賦值的。緩存
首先在auto/options
被初始化爲空。bash
1NGX_PLATFORM=
複製代碼
在執行configure
命令的時候,咱們能夠經過指定crossbuild
參數來主動設置當前的操做系統。微信
1--crossbuild=*) NGX_PLATFORM="$value" ;;
複製代碼
若是咱們沒有在configure
參數中指定上述參數(咱們大多數狀況下也不會指定該選項),那麼nginx
會自動判斷操做系統類型。
在configure
腳本中,咱們看以下內容:架構
1if test -z "$NGX_PLATFORM"; then
2 echo "checking for OS"
3
4 NGX_SYSTEM=`uname -s 2>/dev/null`
5 NGX_RELEASE=`uname -r 2>/dev/null`
6 NGX_MACHINE=`uname -m 2>/dev/null`
7
8 echo " + $NGX_SYSTEM $NGX_RELEASE $NGX_MACHINE"
9
10 NGX_PLATFORM="$NGX_SYSTEM:$NGX_RELEASE:$NGX_MACHINE";
11
12 case "$NGX_SYSTEM" in
13 MINGW32_* | MINGW64_* | MSYS_*)
14 NGX_PLATFORM=win32
15 ;;
16 esac
17
18else
19 echo "building for $NGX_PLATFORM"
20 NGX_SYSTEM=$NGX_PLATFORM
21fi
複製代碼
這一部分就是nginx
判斷操做系統版本的代碼。app
①.
向終端輸出內容,表示開始檢查平臺類型。源碼分析
1echo "checking for OS"
複製代碼
②.
檢測操做系類型,發行版本號,機器體系架構測試
1NGX_SYSTEM=`uname -s 2>/dev/null`
2NGX_RELEASE=`uname -r 2>/dev/null`
3NGX_MACHINE=`uname -m 2>/dev/null`
4
5echo " + $NGX_SYSTEM $NGX_RELEASE $NGX_MACHINE"
6
7NGX_PLATFORM="$NGX_SYSTEM:$NGX_RELEASE:$NGX_MACHINE";
複製代碼
在個人計算機上面,上面的腳本執行以後內容依次是:
1NGX_SYSTEM=Linux
2NGX_RELEASE=3.10.0-693.2.2.el7.x86_64
3NGX_MACHINE=x86_64
複製代碼
說明個人操做系統是3.10
版本的Linux
,當前計算機是x86_64
架構。
so,
1NGX_PLATFORM=Linux:3.10.0-693.2.2.el7.x86_64:x86_64
複製代碼
咱們這個時候分析os/conf
腳本的話,就很是簡單了。
1echo "checking for $NGX_SYSTEM specific features"
2
3case "$NGX_PLATFORM" in
4
5 FreeBSD:*)
6 . auto/os/freebsd
7 ;;
8
9 Linux:*)
10 . auto/os/linux
11 ;;
12
13 SunOS:*)
14 . auto/os/solaris
15 ;;
16
17 Darwin:*)
18 . auto/os/darwin
19 ;;
20
21 win32)
22 . auto/os/win32
23 ;;
24
25 DragonFly:*)
26 have=NGX_FREEBSD . auto/have_headers
27 CORE_INCS="$UNIX_INCS"
28 CORE_DEPS="$UNIX_DEPS $FREEBSD_DEPS"
29 CORE_SRCS="$UNIX_SRCS $FREEBSD_SRCS"
30
31 echo " + sendfile() found"
32 have=NGX_HAVE_SENDFILE . auto/have
33 CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS"
34
35 ngx_spacer='
36'
37 ;;
38
39 NetBSD:*)
40 CORE_INCS="$UNIX_INCS"
41 CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
42 CORE_SRCS="$UNIX_SRCS"
43
44 NGX_RPATH=YES
45 ;;
46
47 HP-UX:*)
48 # HP/UX
49 have=NGX_HPUX . auto/have_headers
50 CORE_INCS="$UNIX_INCS"
51 CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
52 CORE_SRCS="$UNIX_SRCS"
53 CC_AUX_FLAGS="$CC_AUX_FLAGS -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
54 CC_AUX_FLAGS="$CC_AUX_FLAGS -D_HPUX_ALT_XOPEN_SOCKET_API"
55 ;;
56
57 OSF1:*)
58 # Tru64 UNIX
59 have=NGX_TRU64 . auto/have_headers
60 have=NGX_HAVE_STRERROR_R . auto/nohave
61 CORE_INCS="$UNIX_INCS"
62 CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
63 CORE_SRCS="$UNIX_SRCS"
64 ;;
65
66 GNU:*)
67 # GNU Hurd
68 have=NGX_GNU_HURD . auto/have_headers
69 CORE_INCS="$UNIX_INCS"
70 CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
71 CORE_SRCS="$UNIX_SRCS"
72 CC_AUX_FLAGS="$CC_AUX_FLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
73 ;;
74
75 *)
76 CORE_INCS="$UNIX_INCS"
77 CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
78 CORE_SRCS="$UNIX_SRCS"
79 ;;
80
81esac
82
83
84case "$NGX_MACHINE" in
85
86 i386 | i686 | i86pc)
87 have=NGX_HAVE_NONALIGNED . auto/have
88 NGX_MACH_CACHE_LINE=32
89 ;;
90
91 amd64 | x86_64)
92 have=NGX_HAVE_NONALIGNED . auto/have
93 NGX_MACH_CACHE_LINE=64
94 ;;
95
96 sun4u | sun4v | sparc | sparc64)
97 have=NGX_ALIGNMENT value=16 . auto/define
98 # TODO
99 NGX_MACH_CACHE_LINE=64
100 ;;
101
102 ia64 )
103 have=NGX_ALIGNMENT value=16 . auto/define
104 # TODO
105 NGX_MACH_CACHE_LINE=64
106 ;;
107
108 aarch64 )
109 have=NGX_ALIGNMENT value=16 . auto/define
110 NGX_MACH_CACHE_LINE=64
111 ;;
112
113 *)
114 have=NGX_ALIGNMENT value=16 . auto/define
115 NGX_MACH_CACHE_LINE=32
116 ;;
117
118esac
119
120if test -z "$NGX_CPU_CACHE_LINE"; then
121 NGX_CPU_CACHE_LINE=$NGX_MACH_CACHE_LINE
122fi
123
124have=NGX_CPU_CACHE_LINE value=$NGX_CPU_CACHE_LINE . auto/define
複製代碼
1).
向終端輸出提示字符
1echo "checking for $NGX_SYSTEM specific features"
複製代碼
2).
根據NGX_PLATFORM
執行特定腳本
根據上面獲取的NGX_PLATFORM
判斷不一樣的平臺,執行每一個平臺特定的腳本。咱們使用的是linxu
系統,因此執行linux
平臺腳本。
1 Linux:*)
2 . auto/os/linux
3 ;;
複製代碼
這個腳本後面再分析。
3).
根據機器架構設置字節對齊方式以及緩存相關特性
由於個人計算機是x86_64
,因此執行以下腳本:
1 amd64 | x86_64)
2 have=NGX_HAVE_NONALIGNED . auto/have
3 NGX_MACH_CACHE_LINE=64
4 ;;
複製代碼
這裏就是使用auto/have
腳本向NGX_AUTO_CONFIG_H
中寫入:
1#ifndef NGX_AUTO_CONFIG_H
2#define NGX_AUTO_CONFIG_H 1
3#endif
複製代碼
4).
設置緩存行長度數據
1if test -z "$NGX_CPU_CACHE_LINE"; then
2 NGX_CPU_CACHE_LINE=$NGX_MACH_CACHE_LINE
3fi
4
5have=NGX_CPU_CACHE_LINE value=$NGX_CPU_CACHE_LINE . auto/define
複製代碼
由於咱們在auto/cc
編譯器相關的腳本中也設置了NGX_CPU_CACHE_LINE
,因此這裏先判斷NGX_CPU_CACHE_LINE
的值,若是以前沒有設置,那麼就使用auto/os/conf
腳本中的值。
而後將值經過auto/define
寫入到頭文件中。
在上面提到過,nginx
會根據當前的操做系統執行平臺特定腳本。對於個人電腦來講,就是執行auto/os/linux
腳本。下面咱們看一下這個腳本都幹了什麼。
1have=NGX_LINUX . auto/have_headers
2
3CORE_INCS="$UNIX_INCS"
4CORE_DEPS="$UNIX_DEPS $LINUX_DEPS"
5CORE_SRCS="$UNIX_SRCS $LINUX_SRCS"
6
7ngx_spacer='
8'
9
10cc_aux_flags="$CC_AUX_FLAGS"
11CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
12
13
14# Linux kernel version
15
16version=$((`uname -r \
17 | sed -n -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/ \
18 \1*256*256+\2*256+\3/p' \
19 -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1*256*256+\2*256/p'`))
20
21version=${version:-0}
22
23
24# posix_fadvise64() had been implemented in 2.5.60
25
26if [ $version -lt 132412 ]; then
27 have=NGX_HAVE_POSIX_FADVISE . auto/nohave
28fi
29
30# epoll, EPOLLET version
31
32ngx_feature="epoll"
33ngx_feature_name="NGX_HAVE_EPOLL"
34ngx_feature_run=yes
35ngx_feature_incs="#include <sys/epoll.h>"
36ngx_feature_path=
37ngx_feature_libs=
38ngx_feature_test="int efd = 0;
39 struct epoll_event ee;
40 ee.events = EPOLLIN|EPOLLOUT|EPOLLET;
41 ee.data.ptr = NULL;
42 (void) ee;
43 efd = epoll_create(100);
44 if (efd == -1) return 1;"
45. auto/feature
46
47if [ $ngx_found = yes ]; then
48 have=NGX_HAVE_CLEAR_EVENT . auto/have
49 CORE_SRCS="$CORE_SRCS $EPOLL_SRCS"
50 EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE"
51 EVENT_FOUND=YES
52
53
54 # EPOLLRDHUP appeared in Linux 2.6.17, glibc 2.8
55
56 ngx_feature="EPOLLRDHUP"
57 ngx_feature_name="NGX_HAVE_EPOLLRDHUP"
58 ngx_feature_run=no
59 ngx_feature_incs="#include <sys/epoll.h>"
60 ngx_feature_path=
61 ngx_feature_libs=
62 ngx_feature_test="int efd = 0, fd = 0;
63 struct epoll_event ee;
64 ee.events = EPOLLIN|EPOLLRDHUP|EPOLLET;
65 ee.data.ptr = NULL;
66 epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)"
67 . auto/feature
68
69
70 # EPOLLEXCLUSIVE appeared in Linux 4.5, glibc 2.24
71
72 ngx_feature="EPOLLEXCLUSIVE"
73 ngx_feature_name="NGX_HAVE_EPOLLEXCLUSIVE"
74 ngx_feature_run=no
75 ngx_feature_incs="#include <sys/epoll.h>"
76 ngx_feature_path=
77 ngx_feature_libs=
78 ngx_feature_test="int efd = 0, fd = 0;
79 struct epoll_event ee;
80 ee.events = EPOLLIN|EPOLLEXCLUSIVE;
81 ee.data.ptr = NULL;
82 epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)"
83 . auto/feature
84fi
85
86
87# O_PATH and AT_EMPTY_PATH were introduced in 2.6.39, glibc 2.14
88
89ngx_feature="O_PATH"
90ngx_feature_name="NGX_HAVE_O_PATH"
91ngx_feature_run=no
92ngx_feature_incs="#include <sys/types.h>
93 #include <sys/stat.h>
94 #include <fcntl.h>"
95ngx_feature_path=
96ngx_feature_libs=
97ngx_feature_test="int fd; struct stat sb;
98 fd = openat(AT_FDCWD, \".\", O_PATH|O_DIRECTORY|O_NOFOLLOW);
99 if (fstatat(fd, \"\", &sb, AT_EMPTY_PATH) != 0) return 1"
100. auto/feature
101
102
103# sendfile()
104
105CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE"
106ngx_feature="sendfile()"
107ngx_feature_name="NGX_HAVE_SENDFILE"
108ngx_feature_run=yes
109ngx_feature_incs="#include <sys/sendfile.h>
110 #include <errno.h>"
111ngx_feature_path=
112ngx_feature_libs=
113ngx_feature_test="int s = 0, fd = 1;
114 ssize_t n; off_t off = 0;
115 n = sendfile(s, fd, &off, 1);
116 if (n == -1 && errno == ENOSYS) return 1"
117. auto/feature
118
119if [ $ngx_found = yes ]; then
120 CORE_SRCS="$CORE_SRCS $LINUX_SENDFILE_SRCS"
121fi
122
123
124# sendfile64()
125
126CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
127ngx_feature="sendfile64()"
128ngx_feature_name="NGX_HAVE_SENDFILE64"
129ngx_feature_run=yes
130ngx_feature_incs="#include <sys/sendfile.h>
131 #include <errno.h>"
132ngx_feature_path=
133ngx_feature_libs=
134ngx_feature_test="int s = 0, fd = 1;
135 ssize_t n; off_t off = 0;
136 n = sendfile(s, fd, &off, 1);
137 if (n == -1 && errno == ENOSYS) return 1"
138. auto/feature
139
140
141ngx_include="sys/prctl.h"; . auto/include
142
143# prctl(PR_SET_DUMPABLE)
144
145ngx_feature="prctl(PR_SET_DUMPABLE)"
146ngx_feature_name="NGX_HAVE_PR_SET_DUMPABLE"
147ngx_feature_run=yes
148ngx_feature_incs="#include <sys/prctl.h>"
149ngx_feature_path=
150ngx_feature_libs=
151ngx_feature_test="if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) return 1"
152. auto/feature
153
154
155# prctl(PR_SET_KEEPCAPS)
156
157ngx_feature="prctl(PR_SET_KEEPCAPS)"
158ngx_feature_name="NGX_HAVE_PR_SET_KEEPCAPS"
159ngx_feature_run=yes
160ngx_feature_incs="#include <sys/prctl.h>"
161ngx_feature_path=
162ngx_feature_libs=
163ngx_feature_test="if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) return 1"
164. auto/feature
165
166
167# capabilities
168
169ngx_feature="capabilities"
170ngx_feature_name="NGX_HAVE_CAPABILITIES"
171ngx_feature_run=no
172ngx_feature_incs="#include <linux/capability.h>
173 #include <sys/syscall.h>"
174ngx_feature_path=
175ngx_feature_libs=
176ngx_feature_test="struct __user_cap_data_struct data;
177 struct __user_cap_header_struct header;
178
179 header.version = _LINUX_CAPABILITY_VERSION_1;
180 data.effective = CAP_TO_MASK(CAP_NET_RAW);
181 data.permitted = 0;
182
183 (void) header;
184 (void) data;
185 (void) SYS_capset"
186. auto/feature
187
188
189# crypt_r()
190
191ngx_feature="crypt_r()"
192ngx_feature_name="NGX_HAVE_GNU_CRYPT_R"
193ngx_feature_run=no
194ngx_feature_incs="#include <crypt.h>"
195ngx_feature_path=
196ngx_feature_libs=-lcrypt
197ngx_feature_test="struct crypt_data cd;
198 crypt_r(\"key\", \"salt\", &cd);"
199. auto/feature
200
201
202ngx_include="sys/vfs.h"; . auto/include
203
204
205CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
複製代碼
1).
變量初始化
初始化許多變量,咱們看一下腳本就好了,很是簡單。
1have=NGX_LINUX . auto/have_headers
2
3CORE_INCS="$UNIX_INCS"
4CORE_DEPS="$UNIX_DEPS $LINUX_DEPS"
5CORE_SRCS="$UNIX_SRCS $LINUX_SRCS"
6
7ngx_spacer='
8'
9
10cc_aux_flags="$CC_AUX_FLAGS"
11CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
複製代碼
2).
計算Linux
內核版本數字
經過sed
命令計算Linux
的內核版本。
1# Linux kernel version
2
3version=$((`uname -r \
4 | sed -n -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/ \
5 \1*256*256+\2*256+\3/p' \
6 -e 's/^\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1*256*256+\2*256/p'`))
7
8version=${version:-0}
複製代碼
3).
測試Linux
的某些特性
剩下的代碼都是測試Linux
是否支持一些特性,咱們能夠參考以前的auto/feature
文章進行分析。
咱們在本文中詳細的分析了auto/os/
目錄下的腳本。
這一部分的腳本主要是爲了對特定平臺進行初始化,因爲我我的的計算機是Linux
平臺,因此我值分析了auto/os/linux
腳本,其餘的能夠自行分析。
後面的文章咱們會接着分析nginx
的源碼,敬請期待。順便關注個人個公衆號(Nginx源碼分析
)。
Nginx源碼分析
,更多精彩內容第一時間送達