參考網上的資料,寫了一個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