异想天开

What's the true meaning of light, Could you tell me why

nginx源码阅读方法论

日期:2014-05-22 16:40:58
  
最后更新日期:2014-10-27 15:29:16
【技术文章,非码农勿入】
最后更新日期:2014-09-26

1.阅读工具
linux环境用gdb可执行文件,跟踪某个应用场景,windows环境用source insight阅读源码。在源码目录用ctags生成tags文件。与ctags相关的关键字tselect。source insight阅读源码时shift+f8让单词高亮显示,单文件内搜索关键字时f3/f4表示上一个或下一个关键字。

2.nginx编译参数
编译nginx前,objs/Makefile里面的CCFLAGS增加或修改几个参数,修改后如下:
[code lang="cpp"]
CFLAGS = -pipe -g3 -O0 -gdwarf-2 -Wall -Wpointer-arith -Wno-unused-parameter -Werror
[/code]
g3设置调试级别为3,o0优化级别为0,gdwarf-2打开宏定义扩展,这样设置后就可以在gdb时打印宏的值,也不会出现这个值被优化掉的问题。配置文件里面设置worker_processes为1。
3.gdb命令
[code lang="cpp"]
layout src。显示cmd和src双窗口,ctr+x后按a返回之前的单窗口模式;
set follow-fork-mode child。设置fork后,gdb进入子进程;
[/code]
[code lang="cpp"]
info variables ngx_event_actions。
[/code]
查看全局变量ngx_event_actions的定义,也可以使用缩写info var ngx_event_actions,该匹配规则支持正则表达式;
[code lang="cpp"]
info local 查看当前context的局部变量,即栈里面的值
info macro NGX_OK 查看宏NGX_OK的定义位置及值
info funtions 查看所有函数
[/code]
[code lang="cpp"]
pt in_port_t。查看in_port_t的类型,in_port_t为typedef自定义类型
[/code]
[code lang="cpp"]
watch 观察点
[/code]
通过watch设置观察点查看变量在何时被修改,从而bt出执行路径。实际测试时,发现使用watch观察结构体变量时,会非常耗cpu。替代的办法,自定义一个全局整型变量如bz_debug,只在观察点上修改该值,再watch该全局变量,然后就可以print出对应结构体值的变化。还可以使用条件断点,比如
[code lang="cpp"]
b src/core/ngx_conf_file.c:291 if bz_debug==6
[/code]
[code lang="cpp"]
gdb -p PID。实时跟踪某个正在运行的进程。
[/code]

4.如何查看回调函数
nginx封装的事件对象结构体内,有一些回调函数,可以使用addr2line命令,将函数地址转化为对应源码文件的行。

5.多线程调试
set schedule-multiple mode 设置多线程调度关闭(off)或打开(on),关闭时,next就如同跟踪单线程一样
set non-stop on 多线程模型下,其它线程继续运行,这种情况不能使用gdb -p来attach进程下使用

6.linux相关命令查看nginx进程相关信息
pstack查看nginx进程堆栈信息,可以确定nginx阻塞于什么代码点。
ll /proc/${PID}/fd/。查看nginx进程的fd。

主要就是以上这些了,后面用到的会继续更新。