欢迎大家阅读和讨论,转载请注明出处
http://blog.csdn.net/yankai0219/article/details/8093752
内容
0.序
1.情况一:加桩测试函数中没有使用内存池
2.情况二:加桩测试函数中使用内存池
|
0.序
我看到有篇文档讲的是利用gdb来进行Nginx的加桩测试,可是对于我这个从windows转过来的选手,已经习惯了使用IDE来进行调试,一下子让我用gdb进行调试,我还不会~这可就得想法,我之前的文章中有讲过用Eclipse来进行Nginx的开发,那么我就想能否使用Eclipse来进行加桩调试呢?
答案是可喜的,完全可以利用Eclipse进行加桩测试,伟大的Eclipse啊。
我们将会分两种情况来进行说明,一种是加桩测试函数中没有使用内存池,一种是加桩测试函数中使用内存池,有所区别。
1.情况一:加桩测试函数中没有使用内存池
下文中出现的代码是他人的代码,本文章只是介绍调试方法。
1)复制源码
void ngx_slab_test()
{
ngx_shm_t shm;
ngx_slab_pool_t *sp;
u_char *file;
void *one_page;
void *two_page;
ngx_memzero(&shm, sizeof(shm));
shm.size = 4 * 1024 * 1024;
if (ngx_shm_alloc(&shm) != NGX_OK) {
goto failed;
}
printf("test slb\n");
sp = (ngx_slab_pool_t *) shm.addr;
sp->end = shm.addr + shm.size;
sp->min_shift = 3;
sp->addr = shm.addr;
#if (NGX_HAVE_ATOMIC_OPS)
file = NULL;
#else
#error must support NGX_HAVE_ATOMIC_OPS.
#endif
if (ngx_shmtx_create(&sp->mutex, &sp->lock, file) != NGX_OK) {
goto failed;
}
ngx_slab_init(sp);
one_page = ngx_slab_alloc(sp, ngx_pagesize);
two_page = ngx_slab_alloc(sp, 2 * ngx_pagesize);
ngx_slab_free(sp, one_page);
ngx_slab_free(sp, two_page);
ngx_shm_free(&shm);
exit(0);
failed:
printf("failed.\n");
exit(-1);
}
2)在nginx根目录/src/core/nginx.c中添加上面代码,需要改动的有三处:
1.在文件开始处,添加函数声明 void ngx_slab_test();
2.在文件结尾处,添加函数定义:即上述代码
3.在文件中间部位,添加调用函数代码
if (ngx_os_init(log) != NGX_OK) {
return 1;
}
ngx_slab_test();/*edited by yankai*/
3)设置断点,在ngx_slab_test()处设置断点,点击调试按钮,如下图所示
4)进行单步调试,会发现会进行ngx_slab_test函数内部执行。
5)由于我在ngx_slab_test函数中添加了printf语句,因此,在Console窗口中会显示test slb如下图所示:
情况二:加桩测试中使用内存池
在对于
http://code.google.com/p/nginxsrp/wiki/NginxCodeReview 这类牵涉到内存池分配的情况,如何进行加桩测试呢?
方法其实很简单,但是我们必须认识到为什么要按照下面的方法来做。
首先介绍一点基本知识:
nginx对内存的管理均统一完成,例如在特定的生命周期内统一建立内存池。如main函数系统启动初期即分配1024字节大小的内存池。即init_cycle.pool = ngx_create_pool(1024,log);
正是上面这段话决定了我们下面所采用的方法。
注意:本方法中的加桩测试不能用于测试内存池的分配的情况,因为本加桩测试是从已有的init_cycle.pool内存池中分配内存。
错误的做法:我们在加桩测试的函数中自己分配内存池。
如果自己分配内存池,就会造成ngx_create_pool时保存,在单步调试时可以发现会进入ngx_create_pool中报错。
void
test_chain_c()
/*edited by yankai*/
{
ngx_pool_t
* hpnl_pool;
printf
(
"test 1 "
);
hpnl_pool = ngx_create_pool(50,NULL);
//create chain
printf
(
"test 2 "
);
ngx_destroy_pool(hpnl_pool);
exit
(0);
}
|
正确做法:使用init_cycle.pool作为加桩测试的内存池,即加桩测试中的小内存都从init_cycle.pool中获取。
void
test_chain_c(
ngx_cycle_t
*init_cycle)
/*edited by yankai*/
{
ngx_chain_t
*hpnl_cl;
ngx_chain_t
*hpnl_cl_next;
ngx_buf_t
* hpnl_buf;
ngx_buf_t
* hpnl_buf_next;
ngx_str_t
hpnl_str = ngx_string(
"hello"
);
ngx_str_t
hpnl_str_next = ngx_string(
"world"
);
int
hpnl_n;
//create chain
printf
(
"test 1 \n"
);
printf
(
" sizeof(ngx_pool_t) is %d\n"
,
sizeof
(
ngx_pool_t
));
printf
(
"max of init_cycle is %d \n"
,init_cycle->
pool
->
max
);
hpnl_cl = ngx_alloc_chain_link(init_cycle->
pool
);
hpnl_cl_next = ngx_alloc_chain_link(init_cycle->
pool
);
if
( hpnl_cl == NULL || hpnl_cl_next == NULL ){
printf
(
" alloc chain link error\n"
);
exit
(-1);
}
printf
(
"test 2 \n"
);
//create buf
hpnl_buf = ngx_create_temp_buf(init_cycle->
pool
,1000);
hpnl_buf_next = ngx_create_temp_buf(init_cycle->
pool
,1000);
if
(hpnl_buf == NULL || hpnl_buf_next == NULL){
printf
(
" alloc buffer error\n"
);
exit
(-1);
}
//initial chain
hpnl_cl->
buf
= hpnl_buf;
hpnl_cl->
next
= NULL;
hpnl_cl_next->
buf
= hpnl_buf_next;
hpnl_cl_next->
next
= NULL;
if
(hpnl_cl == NULL){
hpnl_cl = hpnl_cl_next;
}
else
{
hpnl_cl->
next
= hpnl_cl_next;
}
hpnl_buf->
last
= ngx_cpymem(hpnl_buf->
last
,hpnl_str.
data
,hpnl_str.
len
);
hpnl_buf_next->
last
= ngx_cpymem(hpnl_buf_next->
last
,hpnl_str_next.
data
,hpnl_str_next.
len
);
printf
(
"begin to output hpnl_cl"
);
hpnl_n = 0;
for
(hpnl_cl_next = hpnl_cl; hpnl_cl_next;hpnl_cl_next = hpnl_cl_next->
next
){
printf
(
"hpnl_cl-> buf->start is %s\n"
,hpnl_cl_next->
buf
->
start
);
printf
(
"@@@%d @@@\n"
,hpnl_n);
hpnl_n++;
}
printf
(
"end up output\n"
);
exit
(0);
}
|
测试步骤:除了代码部分与情况一不同外,其测试方法一样
保存以后点击运行,出现下面结果。
test 1
sizeof(ngx_pool_t) is 40
max of init_cycle is 984
test 2
begin to output hpnl_clhpnl_cl->buf->start is hello
@@@0 @@@
hpnl_cl->buf->start is world
@@@1 @@@
end up output
|