Nginx代碼調試——gdb工具


參考網上的資料,寫了一個configprint模塊,其功能為打印輸出location配置內容,並計數訪問次數。

代碼鏈接如下:https://github.com/PaulWeiHan/nginx_module_development

程序的編寫到運行總不是一帆風順的,編譯通過,運行不過的情況是最讓我抓狂的。

這里記錄一下gdb調試過程。供大家參考:

(這里沒有gdb命令說明,請自行百度)

我使用的是nginx的默認模式即:

daemon on;
master_process on;
worker_processes  1;

我們知道。nginx默認執行的時候,是以daemon模式運行在后台,並且,由master進程fork出多個work子進程來監聽端口的。切到nginx目錄,執行下面命令:

1 gdb
2 shell sbin/nginx
3 shell pidof nginx

這樣,我們就可以得到nginx的pid,一般會是兩個,由於worker子進程是fork master得來的,所以自然worker進程的pid較大。利用gdb的attach和detach命令追蹤worker子進程。

(gdb) shell pidof nginx
11903 11902
(gdb) attach 11903
Attaching to process 11903
Reading symbols from /home/renwh/nginx/sbin/nginx...done.
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/libcrypt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libcrypt.so.1
Reading symbols from /lib64/libpcre.so.0...(no debugging symbols found)...done.
Loaded symbols for /lib64/libpcre.so.0
Reading symbols from /lib64/libz.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libz.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from /lib64/libfreebl3.so...(no debugging symbols found)...done.
Loaded symbols for /lib64/libfreebl3.so
Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/libdl.so.2
Reading symbols from /lib64/libnss_files.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/libnss_files.so.2
0x00000031684e8fb3 in __epoll_wait_nocancel () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64 nss-softokn-freebl-3.14.3-17.el6.x86_64 pcre-7.8-6.el6.x86_64 zlib-1.2.3-29.el6.x86_64
(gdb) 

子進程即worker進程在運行后會停留在epoll_wait處等待相應的事件發生,而這個函數調用被封裝在ngx_process_events_and_timers 中。於是我們在這個函數出設置一個斷點:b ngx_process_events_and_timers.然后采用命令c,使得nginx一直運行,直到遇到第一個斷點:

1 (gdb) b ngx_process_events_and_timers
2 Breakpoint 1 at 0x41b565: file src/event/ngx_event.c, line 195.
3 (gdb) c
4 Continuing.
5 
6 Breakpoint 1, ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:195
7 195     {
8 (gdb) 

進去之后,一直用n向下運行,直到找到ngx_process_events,然后用s追蹤進該函數,一直n,直到運行到epoll_wait,發現,停在了這里,我們知道work子進程在等待事件了。

Breakpoint 1, ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:195
195     {
(gdb) n
199         if (ngx_timer_resolution) {
(gdb) n
204             timer = ngx_event_find_timer();
(gdb) n
218         if (ngx_use_accept_mutex) {
(gdb) n
240         delta = ngx_current_msec;
(gdb) n
242         (void) ngx_process_events(cycle, timer, flags);
(gdb) s
ngx_epoll_process_events (cycle=0x9be050, timer=18446744073709551615, flags=1)
    at src/event/modules/ngx_epoll_module.c:702
702     {
(gdb) n
717         events = epoll_wait(ep, event_list, (int) nevents, timer);
(gdb) n

這時候,你只需要打開一個瀏覽器,訪問你配置好的nginx模塊的url,然后你就會發現gdb可以向下運行了。這時候,你需要在你自己的handler函數處設置斷點,然后c,你會發現,又一次調用了ngx_process_events_and_timers函數,s進入函數,繼續c運行,然后gdb會停在你自己的handler函數入口,這里是:ngx_http_configprint_handler。s追蹤進去,你就可以單步執行你自己寫的handler函數,進行debug了。

 1 (gdb) b ngx_http_configprint_handler
 2 Breakpoint 2 at 0x4699a7: file /home/renwh/src/nginx-1.9.2/configprint//ngx_http_configprint_module.c, line 184.
 3 (gdb) c
 4 Continuing.
 5 
 6 Breakpoint 1, ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:195
 7 195     {
 8 (gdb) s
 9 199         if (ngx_timer_resolution) {
10 (gdb) n
11 204             timer = ngx_event_find_timer();
12 (gdb) n
13 218         if (ngx_use_accept_mutex) {
14 (gdb) n
15 240         delta = ngx_current_msec;
16 (gdb) c
17 Continuing.
18 
19 Breakpoint 2, ngx_http_configprint_handler (r=0x9c8550)
20     at /home/renwh/src/nginx-1.9.2/configprint//ngx_http_configprint_module.c:184
21 184     {
22 (gdb) n
23 189             u_char ngx_my_string[1024] = {0};
24 (gdb) n
25 193             ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_configprint_handler is

gdb不光可以幫你debug,還可以幫你理解整個nginx的運行過程。你可以嘗試在自己的handler掛載函數,loc_conf創建函數等地方添加斷點,來查看整個模塊的調用過程。

個人理解,歡迎討論。聯系方式:rwhsysu@163.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM