今年は、nginx のソース コードを真剣に検討する予定です。その目的は、ネットワーク プログラミングを学ぶことです。私が使用したソース コードの最初のバージョンは nginx-0.1.0-RELEASE、コード アドレスは http://hg.nginx.org/nginx/rev/551102312e19
です。
ブラウザの左側にある zip または gz をクリックしてダウンロードします。解凍後、ソース コード ディレクトリに 4 つのフォルダーが存在します:
auto ディレクトリ内のconfigure ファイルをソース コード ディレクトリにコピーし、.configure
を実行します。
Makefile を生成できます。私の ubuntu では、configure コマンドの出力は次のようになります。
PCRE ライブラリが見つからなかったため、HTTP 書き換えモジュールを正しくインストールできませんでした。構成の概要
+ PCRE ライブラリが見つかりません
+ md5ライブラリは使用されません
+ OpenSSL ライブラリは使用されません
+ システム zlib ライブラリの使用./configure: エラー: HTTP 書き換えモジュールには PCRE ライブラリが必要です。 –without-http_rewrite_module を使用してモジュールを無効にすることもできます
オプションを使用するか、PCRE ライブラリをシステムにインストールするか、PCRE ライブラリをビルドします
–with-pcre= オプションを使用して、nginx でソースから静的に実行します。`
実行コマンド: sudo apt-get install libpcre3 libpcre3-dev
次に、make clean を実行し、結果を表示します:
設定の概要md5 と openssl は使用されません。これについては後ほど説明します。次に make を実行すると、エラーが表示されます。objs/Makefie ファイルを開いて、現在のコンパイル オプションを表示します:+ システム PCRE ライブラリを使用する
nginx パス プレフィックス: /usr/local/nginx
+ md5ライブラリは使用されません
+ OpenSSL ライブラリは使用されません
+ システム zlib ライブラリを使用nginx バイナリ ファイル: /usr/local/nginx/sbin/nginx
nginx 設定ファイル: /usr/local/nginx/conf/nginx.conf
nginx pid ファイル: /usr/local/nginx/logs/nginx.pid
nginx エラー ログ ファイル: /usr/local/nginx/logs/error.log
nginx http アクセス ログ ファイル: /usr/local/nginx/logs/access.log
CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused -Werror -g
その中には
-Werror 警告をエラーとして扱います。警告が発生した場合はコンパイルを中止します。
-Wpointer-arith 関数ポインターまたは void * 型のポインターに対して算術演算を実行するときに警告します。また、非常に便利です。 -壁ではオンになりません。
-pipe 一時ファイルの代わりにパイプを使用します。
-Wno-unused 未使用の変数について警告します
以下のオプションをすべて削除して、再度作成してください。また、表示マクロ ngx_blocking_n がファイル ngx_event_accept.c で宣言されていないというエラーも発生します。objs/Makefile を確認すると、このコンパイル エラーが次のコマンドから発生していることがわかります: gcc -c -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs src/event/ngx_event_accept.c -o ngx_event_accept.o
最後に、ファイル src/os/unix/ngx_socket.h を確認します。定義は次のとおりです。
<code><span>#if (HAVE_FIONBIO)</span><span>int</span> ngx_nonblocking(ngx_socket_t s); <span>int</span> ngx_blocking(ngx_socket_t s); <span>#define ngx_nonblocking_n "ioctl(FIONBIO)"</span><span>#define ngx_blocking_n "ioctl(!FIONBIO)"</span><span>#else</span><span>#define ngx_nonblocking(s) fcntl(s, F_SETFL, O_NONBLOCK)</span><span>#define ngx_nonblocking_n "fcntl(O_NONBLOCK)"</span><span>#define ngx_blocking_n "ioctl(!FIONBIO)"</span><span>#endif</span></code>
IOV_MAX が ngx_writev_chain.c に見つからないことが判明しました。コマンド grep IOV_MAX -r src/os/unix/*
を使用してください
このマクロは freebsd システムでのみ定義されており、core/ngx_config.h に直接追加されることがわかりました。
struct msghdr にはメンバー msg_accrights と msg_accrightslen が存在しないことが判明しました。これらは、オペレーティング システムの 2 つの下位バージョンでのみ使用できる変数名です。ただし、ファイル src 内のコードを確認してください。 /os/unix/ngx_channel.c は次のようになります。
<code><span>#if (HAVE_MSGHDR_MSG_CONTROL)</span> msg.msg_control = (caddr_t) &cmsg; msg.msg_controllen = <span>sizeof</span>(cmsg); <span>#else</span> msg.msg_accrights = (caddr_t) &fd; msg.msg_accrightslen = <span>sizeof</span>(<span>int</span>); <span>#endif</span></code>
<code><span>#define HAVE_MSGHDR_MSG_CONTROL 1</span></code>
今回は対象のファイルは全て生成されましたが、一部のシンボルが見つからないためにエラーが発生しました。
objs/src/core/ngx_times.o: 関数内。 「ngx_time_update」:/home/nginx-0.1.1/src/core/ngx_times.c:179: 「ngx_timezone」への未定義の参照
objs/src/event/ngx_event_accept.o: 関数「ngx_event_accept」内:
/home/nginx-0.1.1/src/event/ngx_event_accept.c:165: 「ngx_blocking」への未定義の参照
objs/src/event/ngx_event_connect.o: 関数「ngx_event_connect_peer」内:
/home/nginx-0.1.1/src/event/ngx_event_connect.c:301: 「ngx_blocking」への未定義の参照
objs/src/event/modules/ngx_rtsig_module.o: 関数「ngx_rtsig_done」内:
/home/nginx-0.1.1/src/event/modules/ngx_rtsig_module.c:173: 「ngx_poll_module_ctx」への未定義の参照
objs/src/event/modules/ngx_rtsig_module.o: 関数「ngx_rtsig_init」内:
/home/nginx-0.1.1/src/event/modules/ngx_rtsig_module.c:134: 「ngx_poll_module_ctx」への未定義の参照
collect2: エラー: ld は 1 つの終了ステータスを返しました
一次全部解决
1 在src/core/ngx_times.c文件里代码又走到了else分支里,然后在 src/os/unix/ngx_time.h中只有solaris才定义了ngx_timezone这个函数:
<code><span>#<span>define</span> ngx_timezone(isdst) (- (isdst ? altzone : timezone) / 60)</span></code>
放开宏定义会发现找不到altzone, 暂时不管这个,把它直接改成0:
<code><span>#<span>define</span> ngx_timezone(isdst) (- (isdst ? 0 : timezone) / 60)</span></code>
2 src/event/ngx_event_accept.c中未定义引用ngx_blocking,原因刚才已经找到了,在src/os/unix/ngx_socket.h中走了else分支,把if里的函数声明直接拷贝一份到else中,因为这是个函数,还有定义部分,在src/os/unix/ngx_socket.c中把这个函数从if宏定义中移出来。 注意,不要修改ngx_nonblocking函数。
3 src/event/modules/ngx_rtsig_module.c中未定义引用ngx_poll_module_ctx,查代码发现这是一个全局变量:
<code><span>extern</span> ngx_event_module_t ngx_poll_module_ctx;</code>
被定义在poll模块内,但编译的时候在objs/Makefile中没有编译这个模块,把它一起编译了,改3个地方,和epoll的编译一样,有epoll的地方直接复制epoll相关的内容,把里面的epoll改成poll就可以了。
最后make成功!
生成了nginx二进制文件。直接./nginx运行,报错:
[emerg] 11732#0: open() /usr/local/nginx/conf/nginx.conf failed (2: No such file or directory)
to be continued…
以上就介绍了nginx 源码(1)编译,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。