转自http://blog.csdn.net/win_lin/article/details/7432611
调试Apache2.2:
- 下载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 - 解压:tar xf httpd-2.2.22.tar.gz
- 进入目录:cd httpd-2.2.22
- 生成Makefile:./configure
- 将优化选项关闭,保证调试时和源码对应:
find . -name "*.mk"|xargs grep --color "\-O2"
find . -name "*.mk"|xargs sed -i "s/-O2/-O0/g"
- 编译和安装:
make
sudo make install - 以root启动调试,需要绑定端口权限(参数指定-X,为调试模式,只启动一个进程一个并发):
sudo
cd /usr/local/apache2/bin
gdbtui httpd
(gdb) b main
(gdb) r -X
调试nginx1.0.15:
- 下载源码:
http://nginx.org/en/download.html
wget http://nginx.org/download/nginx-1.0.15.tar.gz
- 安装依赖库:
sudo yum install -y pcre-devel.x86_64
- 解压和配置:
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
- 启动调试:
sudo
cd /usr/local/nginx/sbin
gdbtui nginx
(gdb) b main
(gdb) r
举个实例:
如何让nignx以单进程运行(不以master和worker,不进入后台)方便调试:
- main():408以单进程启动的代码:
- if (ngx_process == NGX_PROCESS_SINGLE) {ngx_single_process_cycle(cycle);}
- 全局变量ngx_process赋值的地方只有一个 main():363
- if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { ngx_process = NGX_PROCESS_MASTER;}
- 所以,ccf->master为0即可单进程启动。这个是配置项,master在nginx.conf没有,所以看worker_processes是如何设置的。
- 修改配置文件,将worker_processes改为3。启动调试,在变量cycle初始化之后添加观察点:
- gdb nginx
- b main
- r
- # line 333: cycle = ngx_init_cycle(&init_cycle);
- #进入main断点,运行到cycle初始化之后即333行
- u 334
- # 设置观察点
- watch (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes
- u 362
- # 发现没有修改这个值。查看一下这个值:
- p (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes
- # 已经变为了3,所以就是333行初始化的,所以进入ngx_init_cycle看看。
- # 删除所有的断点,重启配置
- delete
- b ngx_init_cycle
- r
- # 观察这个函数,找到cycle和ccf初始化的地方(notepad++选中cycle即可看出它在什么地方赋值),先执行到cycle初始化的地方:
- # line 79: cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
- u 80
- p cycle->conf_ctx
- # 这个时候还没有初始化ccf,观察一下cycle->conf_ctx初始化的地方,执行到这里:
- # line 188: cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
- l 188
- u 189
- p (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes
- # 发现这个时候conf_ctx还没有初始化为数组,所以再观察:
- # line 228: cycle->conf_ctx[ngx_modules[i]->index] = rv;
- u 228
- n
- p (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes
- # 发现这个时候值为-1(还没有加载配置),所以可以设置观察点:
- watch (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes
- # 观察可能改变这个值的代码,应该在line 268: ngx_conf_parse这个地方最有可能会改变,执行到这里:
- u 269
- # 这个时候发现改变了,是函数ngx_conf_set_num_slot设置了这个值,所以设置断点,重启程序:
- # Hardware watchpoint 30: (*(ngx_core_conf_t*)cycle->conf_ctx[0]).worker_processes
- # Old value = -1
- # New value = 3
- # ngx_conf_set_num_slot (cf=0x7fffffffe610, cmd=0x6bbaf8, conf=0x6dca70) at src/core/ngx_conf_file.c:1201
- delete
- b ngx_conf_set_num_slot
- r
- # 进入断点ngx_conf_set_num_slot,查看调用堆栈:
- bt
- #0 ngx_conf_set_num_slot (cf=0x7fffffffe610, cmd=0x6bbaf8, conf=0x6dca70) at src/core/ngx_conf_file.c:1186
- #1 0x000000000041c0e1 in ngx_conf_handler (cf=0x7fffffffe610, last=0) at src/core/ngx_conf_file.c:394
- #2 0x000000000041bc7f in ngx_conf_parse (cf=0x7fffffffe610, filename=0x6dbce0) at src/core/ngx_conf_file.c:244
- #3 0x00000000004189b0 in ngx_init_cycle (old_cycle=0x7fffffffe760) at src/core/ngx_cycle.c:268
- #4 0x00000000004038d0 in main (argc=1, argv=0x7fffffffea28) at src/core/nginx.c:333
- # 可以完全的发现如何调用的配置了。
- # ngx_conf_parse:173 rc = ngx_conf_read_token(cf); 读取一个配置项,可以设断点看看。
- # ngx_conf_handler:289 name = cf->args->elts; 取出配置名称:
- # (gdb) p *name
- # $48 = {len = 16, data = 0x6dcc20 "worker_processes"}
- # ngx_conf_handler:303 cmd = ngx_modules[i]->commands; 循环处理所有的命令,查看这个commands,实际上就是全局变量 ngx_core_commands
- # 在 ngx_core_commands 中可以发现,可以设置master_process来设置master,关于offsetof就是计算偏移量。
- # ngx_conf_handler:394 rv = cmd->set(cf, cmd, conf); 就是调用这个回调函数(ngx_core_commands中定义),进入 ngx_conf_set_num_slot
- 修改配置文件,增加配置项 master_process off; 启动调试:
- delete
- b ngx_conf_set_flag_slot
- #进入断点,可以看到cmd为设置master:
- # (gdb) p *cmd
- # $50 = {name = {len = 14, data = 0x49d702 "master_process"}, type = 16843264, set = 0x41d58e <ngx_conf_set_flag_slot>, conf = 0, offset = 8, post = 0x0}
- 直接设置main的断点,看作用如何:
- delete
- r
- u 362
- # 还需要设置daemon为off
- u 372
- n
- # ccf->master和ccf->daemon这时候为0,会以单进程启动:
- u 408
- # 发现调用了ngx_single_process_cycle(cycle);可以了。
- # origin:15132 master:0 worker:0 listen-80:(15132/nginx)