首頁 > 後端開發 > php教程 > nginx 原始碼(1)編譯

nginx 原始碼(1)編譯

WBOY
發布: 2016-08-08 09:28:09
原創
1276 人瀏覽過

今年準備認真一下nginx源碼,目的是學習網絡編程,我用的源碼公開發布的第一個版本nginx-0.1.0-RELEASE,代碼地址:
http://hg.nginx.org/nginx /rev/551102312e19
在瀏覽器裡直接點左邊的zip或gz就可以下載了。解壓縮後原始碼目錄下有4個資料夾:

  • auto
  • conf
  • docs
  • src

把auto目錄下的configure拷貝到原始碼目錄,執行
. 就可以產生Makefile,同時configure指令的輸出,在我的ubuntu上看起來是這樣的:
Configuration summary

+ PCRE library is not found
+ md5 library is not used

+ OpenSSL library is not used
+ using system zlib library

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using –without-http_rewrite_module

option, or install the PCRE library into the system, or build the PCRE library

statically from the source with nginx by using –with-pcre= option.`


未找到PCRE庫,因此無法正確安裝HTTP rewrite模組。

執行指令:

sudo apt-get install libpcre3 libpcre3-dev

後來執行make clean,configure;顯示結果:
Configuration summary

+ using system PCRE library
+ md5 library is not used

+ OpenSSL library is not used
+ using system zlib library

nginx path prefix: /usr/local/nginx
nginx binary file: /usr/local/nginx/sbin/nginx

nginx configuration file: /usr/local/nginx/conf/nginx.conf

nginx pid file: /usr/local/nginx/logs/nginx.pid
nginx error log file: /usr/local/nginx/logs/error.log
nginx http access log file: /usr/local/nginx/logs/access.log


md5和openssl未使用,這個以後再說。然後make,會出現錯誤,開啟objs/Makefie文件,查看目前的編譯選項:

CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused -Werror -g


其中 -Werror 把警告當作錯誤。出現任何警告就放棄編譯。 -Wpointer-arith 對函數指標或void *類型的指標進行算術操作時給予警告。也很有用。 -Wall 並不會開啟此項目。
-pipe 使用管道代替臨時檔案。
-Wno-unused 未使用的變數給予警告
把後面幾個選項都拿掉,重新make。還會出錯:顯示巨集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,其中的定義如下:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;code&gt;&lt;span&gt;#if (HAVE_FIONBIO)&lt;/span&gt;&lt;span&gt;int&lt;/span&gt; ngx_nonblocking(ngx_socket_t s); &lt;span&gt;int&lt;/span&gt; ngx_blocking(ngx_socket_t s); &lt;span&gt;#define ngx_nonblocking_n &quot;ioctl(FIONBIO)&quot;&lt;/span&gt;&lt;span&gt;#define ngx_blocking_n &quot;ioctl(!FIONBIO)&quot;&lt;/span&gt;&lt;span&gt;#else&lt;/span&gt;&lt;span&gt;#define ngx_nonblocking(s) fcntl(s, F_SETFL, O_NONBLOCK)&lt;/span&gt;&lt;span&gt;#define ngx_nonblocking_n &quot;fcntl(O_NONBLOCK)&quot;&lt;/span&gt;&lt;span&gt;#define ngx_blocking_n &quot;ioctl(!FIONBIO)&quot;&lt;/span&gt;&lt;span&gt;#endif&lt;/span&gt;&lt;/code&gt;</pre><div class="contentsignin">登入後複製</div></div>不含倒數第2行程式碼,那是我新加的,測試發現上面的if分支在ubuntu下是走的else程式碼塊,但else中沒有定義宏ngx_blocking_n,所以加上就好了。

繼續make。

發現在ngx_writev_chain.c中找不到IOV_MAX, 使用指令

grep IOV_MAX -r src/os/unix/*

發現這個巨集只在freebsd系統下才有定義,直接加到core/ngx_config.h中。 繼續make。
發現struct msghdr中沒有成員msg_accrights和msg_accrightslen,這是兩個低版本的作業系統才有的變數名,高版本也有但是名字變了,查看檔案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>
登入後複製

此處已經考慮了版本問題,定義了一個宏來區分,肯定是這個宏未定義,條件走到了else分支所以報錯,直接在文件內定義宏:

<code><span>#define HAVE_MSGHDR_MSG_CONTROL 1</span></code>
登入後複製
繼續make。

這次所有的目標檔案已經生成,但連結的時候出錯了,原因還是一些符號找不到,出錯內容如下:


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: error: ld returned 1 exit status

一次全部解决
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教程有兴趣的朋友有所帮助。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板