用gdb调试apache2.2和nginx

15 篇文章 0 订阅
13 篇文章 0 订阅
转自http://blog.csdn.net/win_lin/article/details/7432611
调试Apache2.2:
  1. 下载apache2.2源码:httpd-2.2.22.tar.gz
    http://projects.apache.org/projects/http_server.html
    wget http://mirror.bjtu.edu.cn/apache//httpd/httpd-2.2.22.tar.gz
  2. 解压:tar xf httpd-2.2.22.tar.gz
  3. 进入目录:cd httpd-2.2.22
  4. 生成Makefile:./configure
  5. 将优化选项关闭,保证调试时和源码对应:
    find . -name "*.mk"|xargs grep --color "\-O2"
    find . -name "*.mk"|xargs sed -i "s/-O2/-O0/g"

  6. 编译和安装:
    make
    sudo make install
  7. 以root启动调试,需要绑定端口权限(参数指定-X,为调试模式,只启动一个进程一个并发):
    sudo
    cd /usr/local/apache2/bin
    gdbtui httpd
    (gdb) b main
    (gdb) r -X

调试nginx1.0.15:

  1. 下载源码:
    http://nginx.org/en/download.html
    wget http://nginx.org/download/nginx-1.0.15.tar.gz
  2. 安装依赖库:
    sudo yum install -y pcre-devel.x86_64
  3. 解压和配置:
    tar xf nginx-1.0.15.tar.gz
    cd nginx-1.0.15
    ./configure
    find . -name "Makefile"|xargs grep --color "\-O\ "
    find . -name "Makefile"|xargs sed -i "s/-O /-O0 /g"
    find . -name "Makefile"|xargs grep --color "\-O"
    make
    sudo make install
  4. 启动调试:
    sudo
    cd /usr/local/nginx/sbin
    gdbtui nginx
    (gdb) b main
    (gdb) r

举个实例:

如何让nignx以单进程运行(不以master和worker,不进入后台)方便调试:

[python]  view plain copy
  1. main():408以单进程启动的代码:  
  2.     if (ngx_process == NGX_PROCESS_SINGLE) {ngx_single_process_cycle(cycle);}  
  3. 全局变量ngx_process赋值的地方只有一个 main():363  
  4.     if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER;}  
  5. 所以,ccf->master为0即可单进程启动。这个是配置项,master在nginx.conf没有,所以看worker_processes是如何设置的。  
  6. 修改配置文件,将worker_processes改为3。启动调试,在变量cycle初始化之后添加观察点:  
  7.     gdb nginx  
  8.     b main  
  9.     r  
  10.     # line 333: cycle = ngx_init_cycle(&init_cycle);  
  11.     #进入main断点,运行到cycle初始化之后即333行  
  12.     u 334  
  13.     # 设置观察点  
  14.     watch (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes  
  15.     u 362  
  16.     # 发现没有修改这个值。查看一下这个值:  
  17.     p (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes  
  18.     # 已经变为了3,所以就是333行初始化的,所以进入ngx_init_cycle看看。  
  19.     # 删除所有的断点,重启配置  
  20.     delete  
  21.     b ngx_init_cycle  
  22.     r  
  23.     # 观察这个函数,找到cycle和ccf初始化的地方(notepad++选中cycle即可看出它在什么地方赋值),先执行到cycle初始化的地方:  
  24.     # line 79: cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));  
  25.     u 80  
  26.     p cycle->conf_ctx  
  27.     # 这个时候还没有初始化ccf,观察一下cycle->conf_ctx初始化的地方,执行到这里:  
  28.     # line 188: cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));  
  29.     l 188  
  30.     u 189  
  31.     p (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes  
  32.     # 发现这个时候conf_ctx还没有初始化为数组,所以再观察:  
  33.     # line 228: cycle->conf_ctx[ngx_modules[i]->index] = rv;  
  34.     u 228  
  35.     n  
  36.     p (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes  
  37.     # 发现这个时候值为-1(还没有加载配置),所以可以设置观察点:  
  38.     watch (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes  
  39.     # 观察可能改变这个值的代码,应该在line 268: ngx_conf_parse这个地方最有可能会改变,执行到这里:  
  40.     u 269  
  41.     # 这个时候发现改变了,是函数ngx_conf_set_num_slot设置了这个值,所以设置断点,重启程序:  
  42.     # Hardware watchpoint 30: (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes  
  43.     # Old value = -1  
  44.     # New value = 3  
  45.     # ngx_conf_set_num_slot (cf=0x7fffffffe610, cmd=0x6bbaf8, conf=0x6dca70) at src/core/ngx_conf_file.c:1201  
  46.     delete  
  47.     b ngx_conf_set_num_slot  
  48.     r  
  49.     # 进入断点ngx_conf_set_num_slot,查看调用堆栈:  
  50.     bt  
  51.     #0  ngx_conf_set_num_slot (cf=0x7fffffffe610, cmd=0x6bbaf8, conf=0x6dca70) at src/core/ngx_conf_file.c:1186  
  52.     #1  0x000000000041c0e1 in ngx_conf_handler (cf=0x7fffffffe610, last=0) at src/core/ngx_conf_file.c:394  
  53.     #2  0x000000000041bc7f in ngx_conf_parse (cf=0x7fffffffe610, filename=0x6dbce0) at src/core/ngx_conf_file.c:244  
  54.     #3  0x00000000004189b0 in ngx_init_cycle (old_cycle=0x7fffffffe760) at src/core/ngx_cycle.c:268  
  55.     #4  0x00000000004038d0 in main (argc=1, argv=0x7fffffffea28) at src/core/nginx.c:333  
  56.     # 可以完全的发现如何调用的配置了。  
  57.     # ngx_conf_parse:173 rc = ngx_conf_read_token(cf); 读取一个配置项,可以设断点看看。  
  58.     # ngx_conf_handler:289 name = cf->args->elts; 取出配置名称:  
  59.     #                                           (gdb) p *name   
  60.     #                                            $48 = {len = 16, data = 0x6dcc20 "worker_processes"}  
  61.     # ngx_conf_handler:303 cmd = ngx_modules[i]->commands; 循环处理所有的命令,查看这个commands,实际上就是全局变量 ngx_core_commands  
  62.     #                   在 ngx_core_commands 中可以发现,可以设置master_process来设置master,关于offsetof就是计算偏移量。  
  63.     # ngx_conf_handler:394 rv = cmd->set(cf, cmd, conf); 就是调用这个回调函数(ngx_core_commands中定义),进入 ngx_conf_set_num_slot  
  64. 修改配置文件,增加配置项 master_process off; 启动调试:  
  65.     delete  
  66.     b ngx_conf_set_flag_slot  
  67.     #进入断点,可以看到cmd为设置master:  
  68.     #                   (gdb) p *cmd  
  69.     #                   $50 = {name = {len = 14, data = 0x49d702 "master_process"}, type = 16843264, set = 0x41d58e <ngx_conf_set_flag_slot>, conf = 0, offset = 8, post = 0x0}  
  70. 直接设置main的断点,看作用如何:  
  71.     delete  
  72.     r  
  73.     u 362  
  74.     # 还需要设置daemon为off  
  75.     u 372  
  76.     n  
  77.     # ccf->master和ccf->daemon这时候为0,会以单进程启动:  
  78.     u 408  
  79.     # 发现调用了ngx_single_process_cycle(cycle);可以了。  
  80.     # origin:15132 master:0 worker:0 listen-80:(15132/nginx)  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值