Nginx代码调试——gdb工具
参考网上的资料,写了一个configprint模块,其功能为打印输出location配置内容,并计数访问次数。
代码链接如下:https://github.com/PaulWeiHan/nginx_module_development
程序的编写到运行总不是一帆风顺的,编译通过,运行不过的情况是最让我抓狂的。
这里记录一下gdb调试过程。供大家参考:
(这里没有gdb命令说明,请自行百度)
我使用的是nginx的默认模式即:
daemon on;
master_process on;
worker_processes ;
我们知道。nginx默认执行的时候,是以daemon模式运行在后台,并且,由master进程fork出多个work子进程来监听端口的。切到nginx目录,执行下面命令:
gdb
shell sbin/nginx
shell pidof nginx
这样,我们就可以得到nginx的pid,一般会是两个,由于worker子进程是fork master得来的,所以自然worker进程的pid较大。利用gdb的attach和detach命令追踪worker子进程。
(gdb) shell pidof nginx (gdb) attach
Attaching to process
Reading symbols from /home/renwh/nginx/sbin/nginx...done.
Reading symbols from /lib64/libpthread.so....(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.
Reading symbols from /lib64/libcrypt.so....(no debugging symbols found)...done.
Loaded symbols for /lib64/libcrypt.so.
Reading symbols from /lib64/libpcre.so....(no debugging symbols found)...done.
Loaded symbols for /lib64/libpcre.so.
Reading symbols from /lib64/libz.so....(no debugging symbols found)...done.
Loaded symbols for /lib64/libz.so.
Reading symbols from /lib64/libc.so....(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.
Reading symbols from /lib64/ld-linux-x86-.so....(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-.so.
Reading symbols from /lib64/libfreebl3.so...(no debugging symbols found)...done.
Loaded symbols for /lib64/libfreebl3.so
Reading symbols from /lib64/libdl.so....(no debugging symbols found)...done.
Loaded symbols for /lib64/libdl.so.
Reading symbols from /lib64/libnss_files.so....(no debugging symbols found)...done.
Loaded symbols for /lib64/libnss_files.so.
0x00000031684e8fb3 in __epoll_wait_nocancel () from /lib64/libc.so.
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64 nss-softokn-freebl-3.14.-.el6.x86_64 pcre-7.8-.el6.x86_64 zlib-1.2.-.el6.x86_64
(gdb)
子进程即worker进程在运行后会停留在epoll_wait处等待相应的事件发生,而这个函数调用被封装在ngx_process_events_and_timers 中。于是我们在这个函数出设置一个断点:b ngx_process_events_and_timers.然后采用命令c,使得nginx一直运行,直到遇到第一个断点:
(gdb) b ngx_process_events_and_timers
Breakpoint at 0x41b565: file src/event/ngx_event.c, line .
(gdb) c
Continuing. Breakpoint , ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:
{
(gdb)
进去之后,一直用n向下运行,直到找到ngx_process_events,然后用s追踪进该函数,一直n,直到运行到epoll_wait,发现,停在了这里,我们知道work子进程在等待事件了。
Breakpoint , ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:
{
(gdb) n
if (ngx_timer_resolution) {
(gdb) n
timer = ngx_event_find_timer();
(gdb) n
if (ngx_use_accept_mutex) {
(gdb) n
delta = ngx_current_msec;
(gdb) n
(void) ngx_process_events(cycle, timer, flags);
(gdb) s
ngx_epoll_process_events (cycle=0x9be050, timer=, flags=)
at src/event/modules/ngx_epoll_module.c:
{
(gdb) n
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了。
(gdb) b ngx_http_configprint_handler
Breakpoint at 0x4699a7: file /home/renwh/src/nginx-1.9./configprint//ngx_http_configprint_module.c, line 184.
(gdb) c
Continuing. Breakpoint , ngx_process_events_and_timers (cycle=0x9be050) at src/event/ngx_event.c:
{
(gdb) s
if (ngx_timer_resolution) {
(gdb) n
timer = ngx_event_find_timer();
(gdb) n
if (ngx_use_accept_mutex) {
(gdb) n
delta = ngx_current_msec;
(gdb) c
Continuing. Breakpoint , ngx_http_configprint_handler (r=0x9c8550)
at /home/renwh/src/nginx-1.9./configprint//ngx_http_configprint_module.c:184
{
(gdb) n
u_char ngx_my_string[] = {};
(gdb) n
ngx_log_error(NGX_LOG_EMERG, r->connection->log, , "ngx_http_configprint_handler is
gdb不光可以帮你debug,还可以帮你理解整个nginx的运行过程。你可以尝试在自己的handler挂载函数,loc_conf创建函数等地方添加断点,来查看整个模块的调用过程。
个人理解,欢迎讨论。联系方式:rwhsysu@163.com
Nginx代码调试——gdb工具的更多相关文章
- C++雾中风景番外篇3:GDB与Valgrind ,调试代码内存的工具
写 C++的同学想必有太多和内存打交道的血泪经验了,常常被 C++的内存问题搅的焦头烂额.(写 core 的经验了)有很多同学一见到 core 就两眼一抹黑,不知所措了.笔者 入"坑&quo ...
- GDB代码调试与使用
GDB代码调试与使用 Linux下GDB调试代码 源代码 编译生成执行文件 gcc -g test.c -o test 使用GDB调试 启动GDB:gdb test 从第一行列出源代码:list 直接 ...
- nginx源代码分析--GDB调试
利用gdb[i]调试nginx[ii]和利用gdb调试其他程序没有两样,只是nginx能够是daemon程序,也能够以多进程执行,因此利用gdb调试和寻常会有些许不一样. 当然,我们能够选择将ngin ...
- C/C++调试分析工具
一.静态分析工具 cppcheck cppcheck主要用于对C/C++源代码进行分析检查的一个开源工具,可以用来检测未使用的变量.越界访问.内存泄漏等问题. 使用方法 cppcheck --enab ...
- Linux下C语言的调试 - gdb
调试是每个程序员都会面临的问题. 如何提高程序员的调试效率, 更好更快地定位程序中的问题从而加快程序开发的进度, 是大家共同面对的问题. 可能Windows用户顺口就会说出:用VC呗 :-) , 它提 ...
- 调试分析工具 (C/C++)
一.静态分析工具 cppcheck cppcheck主要用于对C/C++源代码进行分析检查的一个开源工具,可以用来检测未使用的变量.越界访问.内存泄漏等问题. 使用方法 cppcheck --enab ...
- 11个Visual Studio代码性能分析工具
软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和 ...
- Android开发调试日志工具类[支持保存到SD卡]
直接上代码: package com.example.callstatus; import java.io.File; import java.io.FileWriter; import java.i ...
- Asp.net mvc 5 CRUD代码自动生成工具- vs.net 2013 Saffolding功能扩展
Asp.net mvc 5 CRUD代码自动生成工具 -Visual Studio.net2013 Saffolding功能扩展 上次做过一个<Asp.net webform scaffoldi ...
随机推荐
- 练习--LINUX进程间通信之信号SIGNAL
同样的,信号也不要太迷信可靠信号及不及靠信号,实时或非实时信号. 但必须要了解这些信号之间的差异,函数升级及参数,才能熟练运用. ~~~~~~~~~~~~~~~~ 信号本质 信号是在软件层次上对中断机 ...
- php获取请求的方式(get/post)
$request_method = $_SERVER['REQUEST_METHOD'];//用什么方式访问 get post
- js构造函数
使用函数做自动化 function createObj(nick, age){ var obj = { nick: nick, age: age, printName: function(){ con ...
- Altium Designer 特定网络取消 remove loops
在使用Altium Designer时,在PCB Editor 里面可以设定是否需要Automatically remove Loops,但是这个设置是全局的,在设计时难免会遇到对大部分网络是需要删除 ...
- HDU 4288 Coder 【线段树+离线处理+离散化】
题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...
- 存储过程系列之调试存储过程 SQL Server 2005
在数据库中直接调试 在数据库中直接调试是调试SQL Server 2005的存储过程的最简单的方法. 在Visual Stuido的IDE中你可以选择单步执行存储过程,然后就可以一条语句一条语句地单 ...
- hdu1501Zipper(记忆化搜索)
http://acm.hdu.edu.cn/showproblem.php?pid=1501 搜了下记忆化搜索是嘛 然后就看到这个题了 不过一不小心看到代码了 代码又那么短 一不小心给记住了 然后看了 ...
- Struts 2.3.1.1 命令执行漏洞
漏洞版本: Struts 2.3.1.1 漏洞描述: CVE ID:CVE-2011-3923 Struts2的核心使用的是WebWork框架,而WebWork通过XWork来处理用户的请求参数.Xw ...
- Linux Kernel ‘oz_cdev_write()’函数本地缓冲区溢出漏洞
漏洞名称: Linux Kernel ‘oz_cdev_write()’函数本地缓冲区溢出漏洞 CNNVD编号: CNNVD-201311-060 发布时间: 2013-11-07 更新时间: 201 ...
- ruby2.2.2在msvc2010上编译
ruby2.2.2在msvc2010上编译有些问题,主要是msvc2010不支持c99,ruby有些扩展源代码例如ffi.c局部变量没有在block的起始位置定义,导致编译器报错. 办法 1.用支持c ...