《深入剖析Nginx》——2.5 加桩调试

简介:

本节书摘来自异步社区《深入剖析Nginx》一书中的第2章,第2.5节,作者: 高群凯 更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.5 加桩调试

如果我们对代码做过单元测试,那么肯定知道加桩的概念,简单点说就是为了让一个模块执行起来,额外添加的一些支撑代码。比如,我要简单测试一个实现某种排序算法的子函数的功能是否正常,那么我也许需要写一个main()函数,设置一个数组,提供一些乱序的数据,然后利用这些数据调用排序子函数(假设它提供的接口就是对数组的排序),然后printf打印排序后的结果,看是否排序正常,所有写的这些额外代码(main()函数、数组、printf打印)就是桩代码。

上面提到的这种用于单元测试的方法,同样也可以用来深度调试Nginx内部逻辑,而且Nginx很多的基础实现(比如slab机制、红黑树、chain链、array数组等)都比较独立,要调试它们只需提供少量的桩代码即可。

以Nginx的slab机制为例,我们通过下面所提供的这些桩代码即可调试该功能的具体实现。Nginx 的 slab 机制用于对多进程共享内存的管理,不过单进程也是一样的执行逻辑,除了加/解锁直通以外(即加锁时必定成功),所以我们采取最简单的办法,直接在 Nginx 本身的main()函数内插入我们的桩代码。当然,必须根据具体情况把桩代码放在合适的调用位置,比如这里的slab机制就依赖一些全局变量(像ngx_pagesize等),所以需要把桩代码的调用位置放在这些全局变量的初始化之后。

197: 代码片段2.5-1,文件名: nginx.c
198: void ngx_slab_test()
199: {
200:       ngx_shm_t shm;
201:       ngx_slab_pool_t *sp;
202:       u_char *file;
203:       void *one_page;
204:       void *two_page;
205:     
206:       ngx_memzero(&shm, sizeof(shm));
207:       shm.size = 4 * 1024 * 1024;
208:       if (ngx_shm_alloc(&shm) != NGX_OK) {
209:              goto failed;
210:       }
211:     
212:      sp = (ngx_slab_pool_t *) shm.addr;
213:      sp->end = shm.addr + shm.size;
214:      sp->min_shift = 3;
215:      sp->addr = shm.addr;
216: 
217: #if (NGX_HAVE_ATOMIC_OPS)
218:       file = NULL;
219: #else
220:      #error must support NGX_HAVE_ATOMIC_OPS.
221: #endif
222:      if (ngx_shmtx_create(&sp->mutex, &sp->lock, file) != NGX_OK) {
223:             goto failed;
224:      }
225:     
226:      ngx_slab_init(sp);
227:     
228:      one_page = ngx_slab_alloc(sp, ngx_pagesize);
229:      two_page = ngx_slab_alloc(sp, 2 * ngx_pagesize);
230: 
231:      ngx_slab_free(sp, one_page);
232:      ngx_slab_free(sp, two_page);
233:     
234:      ngx_shm_free(&shm);
235:     
236:      exit(0);
237: failed:
238:      printf("failed.\n");
239:      exit(-1);
240: }
241: …
353:      if (ngx_os_init(log) != NGX_OK) {
354:             return 1;
355:      }
356:     
357:      ngx_slab_test();
358: …

上面是修改之后的nginx.c源文件,直接make后生成新的Nginx,不过这个可执行文件不再是一个Web服务器,而是一个简单的调试slab机制的辅助程序。可以看到,程序在进入main()函数后先做一些初始化工作,然后通过ngx_slab_test()函数调入到桩代码内执行调试逻辑,完成既定目标后便直接exit()退出整个程序。

正常运行时,Nginx本身对内存的申请与释放是不可控的,所以直接去调试Nginx内存管理的slab机制的相关代码逻辑非常困难,利用这种加桩的办法,ngx_slab_alloc()申请内存和ngx_slab_free()释放内存都能精确控制,对每一次内存的申请或释放后,slab机制的内部结构发生了怎样的变化都能准确地掌握,对其相关逻辑的理解也就没有那么困难了。

相关文章
|
3月前
|
应用服务中间件 nginx
vs2013调试nginx
vs2013调试nginx
|
8月前
|
测试技术 应用服务中间件 nginx
nginx实现的测试环境请求复制到本地,并进行debug调试
nginx实现的测试环境请求复制到本地,并进行debug调试
136 0
|
网络协议 应用服务中间件 nginx
浏览器debug 调试一打开 Nginx 就 504 Gateway Time-out
浏览器debug 调试一打开 Nginx 就 504 Gateway Time-out
232 0
浏览器debug 调试一打开 Nginx 就 504 Gateway Time-out
|
NoSQL 应用服务中间件 nginx
|
应用服务中间件 nginx JavaScript