学习bind9源码之前,首先要知道如何用gdb来调试bind。BIND9的源码我是先看代码弄懂它的架构,像什么event-drive,epoll等,
再去看它的业务流程。看业务流程的时候要追踪它的数据流和处理过程,所以用gdb比较好,当然自己加日志再结合BIND9自有的日志也不是不
行,只是觉得这样更清晰。
编译bind的时候加的有-g和-O2选项,前者不用说了,后者很坑爹的,用gdb调试时会发现代码的实际执行顺序会有所改变,这是编译器的优化。
编译器的优化有三级,-O2就是二级优化的意思,扯远了,总之是去掉比较好吧,我自己调试时是没去的,习惯了。
一步步来:
1.gdb named
gdb>set args -g -n1 -d5
set args就是设置程序的运行参数,- g就是说前台运行,可以看到打印的日志等信息,-n是指worker线程的个数(这个要是不懂就看另外一篇,BIND9
的架构与机制(-_-还没写....)),这个很重要,本来的工作是按照顺序执行的,那么打印的日志也必然是按照顺序打印出来,一一匹配,如A->B->C->D,
如果worker线程个数大于1的话,那么很可能另外一个线程先把事C执行打印了日志,而此时可能B在执行日志还没打印,看到的日志顺序就和业务处理的
逻辑顺序不一样了,可能看到的日志顺序就感觉莫名其妙。-d就是bind的自有调试记录,5就是等级,bind的日志我没有咋看,有很多宏如CTRACE,FTRACE,
函数ns_client_log(不知道是不是这个,也可能记错了)等,-5应该就满足所有等级的要求,其内部的打印都会打印出来。大部分是函数的开头或结尾打印一下。
gdb>b client_request
这个是设置断点,断点为client_request,之所以设置这一个就是因为bind是事件驱动的,而受到查询或者是其它(notify等)消息,执行的第一个函数即为此,
即所有的dns报文的处理入口都是client_request。
gdb>r
那么程序就开始了。
2.set print pretty on,设置打印结构体,好看一点....
print /x ###打印比如sockaddr_in这种,由于字节序的不同,看十进制的数不如看16进制的。
其它都是gdb的基本操作了