nginx学习(一)内存
网上有很多关于内存的学习,此学习的目的是为了能将内存用法化为自己的东西灵活用在别处.总体思路是化整为零.
参考其它的文章地址:http://blog.csdn.net/v_july_v/article/details/7040425
先依此画张图:
内存池的结构比较简单,有几点需特别说明:
1)内存池在使用之前需创建,如
pool = ngx_create_pool(1024, NULL);
2)在使用内存池的时候均通过p = ngx_palloc(pool, 512);分配内存.
3)第一个内存块与后续的内存块的大小有些微的差异,以1024大小的内存池为例,第一个内存块的数据区大小为1024-sizeof(ngx_pool_s) = 984,第二个以及后续的内存块的数据区的大小则为1024-sizeof(ngx_pool_data_t) = 1008,如上图所示.
4)关于字段failed,源代码中有这样一组代码:
for (p = current; p->d.next; p = p->d.next) {
if (p->d.failed++ > 4) {
current = p->d.next;
}
}
之前一直不理解,网上很多人说是一组经验值,后来写了好些测试代码,不停分配内存池,突然想明白了,也明白了pool->current不一定指向当前内存块的意思.理解如下:
内存池实际上是一个链式结构,如果分配内存的时候总是从头开始,一旦内存池中的块特别多,则会影响效率,因此增加了一个current的指针,当分配策略达到一定程度的时候,将current后移,后面的分配不再使用current之前的内存(即使之前的内存块可用),这样以空间换时间,使得效率尽可能高.
5)内存池的分配一旦调用了ngx_palloc,p指向的是分配的内存,此时当前的内存池中的last变量已经指向了当前内存的末端,此处特别需要注意.
测试代码如下:
void dump_pool(ngx_pool_t* pool) { while (pool) { printf("pool = 0x%x\n", pool); printf(" .d\n"); printf(" .last = 0x%x\n", pool->d.last); printf(" .end = 0x%x\n", pool->d.end); printf(" .next = 0x%x\n", pool->d.next); printf(" .failed = %d\n", pool->d.failed); printf(" .max = %d\n", pool->max); printf(" .current = 0x%x\n", pool->current); printf(" .chain = 0x%x\n", pool->chain); printf(" .large = 0x%x\n", pool->large); printf(" .cleanup = 0x%x\n", pool->cleanup); printf(" .log = 0x%x\n", pool->log); printf("available pool memory = %d\n\n", pool->d.end - pool->d.last); pool = pool->d.next; } } int test_main() { ngx_pool_t *pool; char *p = NULL; int i = 0; printf("sizeof(ngx_pool_t) = %d\n", sizeof(ngx_pool_t));//ngx_pool_data_t printf("sizeof(ngx_pool_data_t) = %d\n", sizeof(ngx_pool_data_t)); printf("--------------------------------\n"); printf("create a new pool:\n"); printf("--------------------------------\n"); pool = ngx_create_pool(1024, NULL); dump_pool(pool); for (i = 0; i < 10; i++) { printf("--------------------------------\n"); printf("alloc block %d from the pool:\n", i+1); printf("--------------------------------\n"); p = ngx_palloc(pool, 512); dump_pool(pool); } ngx_destroy_pool(pool); return 0; }