nginx的内存池及内存管理
来源:互联网 发布:同城网络2018招财务吗 编辑:程序博客网 时间:2024/06/06 14:22
nginx对内存的管理是由自己实现的内存池结构ngx_pool_t来完成,本文主要讲nginx的内存管理。
nginx对内存管理涉及到四个文件:src/core/ngx_palloc.h、src/core/ngx_palloc.c、src/os/unix/ngx_alloc.c、src/os/unix/ngx_alloc.h
ngx_alloc.h和ngx_alloc.c文件主要是对malloc、calloc、free、posix_memalign和memalign的封装,分别被封装为ngx_alloc、ngx_calloc、ngx_free和ngx_memalign
ngx_alloc:封装malloc分配内存
ngx_calloc:封装malloc分配内存,并初始化为0
ngx_memalign:返回基于alignment对齐的大小为size的内存空间,即地址为alignment的整数倍,也是2的幂
ngx_palloc.c文件中主要是对内存池的创建及销毁,从内存池中分配内存。
内存池结构
nginx对内存的管理统一完成,在nginx启动时,分配的是1024B大小的内存池,需要内存时从内存池中分配内存,在适当的时候释放内存池的内存(如关闭http连接时调用ngx_destroy_pool)。nginx中内存池结构定义为ngx_pool_t,其内存池结构如下。
typedef struct { u_char *last;//内存池中的内存分配到此处,也是下一次分开始位置 u_char *end; //内存池的结束地址 ngx_pool_t *next;//指向下一块内存,也可以称为内存池 ngx_uint_t failed;//分配失败的次数} ngx_pool_data_t;//内存池中数据的信息struct ngx_pool_s { ngx_pool_data_t d;//内存池中的数据块 size_t max; //内存池中用于存放数据的容量 ngx_pool_t *current; //指向当前内存池 ngx_chain_t *chain; //指向下一个ngx_chain_t结构 ngx_pool_large_t *large; //大块内存链表,即内存大小大于max ngx_pool_cleanup_t *cleanup; //释放内存池的回调 ngx_log_t *log;//日志信息};像还有其它一些结构,如清除操作、大块数据链表,如下
#define NGX_MAX_ALLOC_FROM_POOL (ngx_pagesize - 1)#define NGX_DEFAULT_POOL_SIZE (16 * 1024)#define NGX_POOL_ALIGNMENT 16#define NGX_MIN_POOL_SIZE \ ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)), \ NGX_POOL_ALIGNMENT)typedef void (*ngx_pool_cleanup_pt)(void *data); //清除操作的回调typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t;struct ngx_pool_cleanup_s { ngx_pool_cleanup_pt handler; void *data; ngx_pool_cleanup_t *next;};typedef struct ngx_pool_large_s ngx_pool_large_t;struct ngx_pool_large_s { ngx_pool_large_t *next; //指向下一个大块内存 void *alloc; //指向分配的大块内存};内存池操作
1、内存池创建
创建内存池由函数ngx_create_pool来完成。代码如下
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log){ ngx_pool_t *p; p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log); if (p == NULL) { return NULL; } p->d.last = (u_char *) p + sizeof(ngx_pool_t);//指向ngx_pool_t结构之后,也以下次内存分配的开始 p->d.end = (u_char *) p + size;//指向内存池的结束位置 p->d.next = NULL; p->d.failed = 0; size = size - sizeof(ngx_pool_t);//指定的分配大小减去ngx_pool_t结构体的大小(40B) p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL; //最大不会超过4095 p->current = p; p->chain = NULL; p->large = NULL; p->cleanup = NULL; p->log = log; return p;}2、内存池销毁
销毁内存池由函数ngx_destroy_pool完成。
遍历cleanup链表,如果有回调函数,就回调处理;遍历large大内存链表,释放分配的大块内存;遍历数据块的链表,将分配的小块内存释放。
3、内存池重置
重置由函数ngx_reset_pool完成。
释放large链表的大块内存,将数据块的last指针置为ngx_pool_t后,与创建时的位置相同。
4、分配内存
分配内存的函数有四个
void *ngx_palloc(ngx_pool_t *pool, size_t size)
void *ngx_pnalloc(ngx_pool_t *pool, size_t size)
void *ngx_pcalloc(ngx_pool_t *pool, size_t size)
void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
ngx_palloc代码分析如下
void *ngx_palloc(ngx_pool_t *pool, size_t size){ u_char *m; ngx_pool_t *p;//分配的大小不大于内存池的容量 if (size <= pool->max) { p = pool->current; do { m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); //将下一次分配的地址NGX_ALIGNMENT对齐//内存池中的剩余大小可以装下size if ((size_t) (p->d.end - m) >= size) { p->d.last = m + size; return m; } p = p->d.next; } while (p);//在已有的内存池中没有找到可以分配size大小的空间,就再申请一个内存块。 return ngx_palloc_block(pool, size); }//分配的大小大于内存池的容量,就大块内存分配 return ngx_palloc_large(pool, size);}ngx_palloc_block函数分析如下
void *ngx_palloc_block(ngx_pool_t *pool, size_t size){ u_char *m; size_t psize; ngx_pool_t *p, *new; psize = (size_t) (pool->d.end - (u_char *) pool); //计算内存池的大小 m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); //分配一个与内存池一样大小的内存块 if (m == NULL) { return NULL; } new = (ngx_pool_t *) m; new->d.end = m + psize;//与创建内存池一样,设置内存块的结束位置 new->d.next = NULL; new->d.failed = 0; m += sizeof(ngx_pool_data_t); m = ngx_align_ptr(m, NGX_ALIGNMENT); new->d.last = m + size; //设置当前内存块的使用到的位置,即下一次分配内存的开始 for (p = pool->current; p->d.next; p = p->d.next) { if (p->d.failed++ > 4) { pool->current = p->d.next;//设置内存池的current指针 } } p->d.next = new; return m;}注意:该函数分配一块内存后,last指针指向的是ngx_pool_data_t结构体(16B)之后数据区的起始位置,而创建内存池, 指向的是ngx_pool_t结构体之后数据区的起始位置。
5、释放内存
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p)
该函数只是释放large链表中分配的内存。
6、注册cleanup
由函数ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)完成。
- nginx的内存池及内存管理
- nginx内存池ngx_pool_t 及内存管理
- Nginx源码分析---内存池结构ngx_pool_t及内存管理
- Nginx内存池结构ngx_pool_t及内存管理
- nginx内存池管理
- nginx内存池管理
- nginx内存池管理
- Nginx 内存池管理
- Nginx 内存池管理
- 借用nginx内存池来管理自己的程序内存
- Nginx内存管理及数据结构浅析–共享内存的实现
- Nginx内存管理及数据结构浅析–共享内存的实现
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- an'droid屏幕适配
- eclipse 中的注释 快捷键
- 网上支付说明以及工商银行网上支付流程
- hdu5163---Taking Bus
- Graphlab user guide笔记
- nginx的内存池及内存管理
- ubuntu下开启wifi的几种办法,安卓可链接
- 优先队列(二叉堆)的插入程序
- 条件化简(二)
- struts2 hello world 搭建
- 近期android开发弯路总结(在EditText里面显示图片,并getText时图片占位设定为设定字符)
- Hbase -- 表的设计
- 如果更注重成本,从长期来看,成本将增加、质量将下降;如果更注重质量,从长期来看,成本将下降、质量将提升
- URL: http://liaozhongmin:50060/tasklog?taskid=attempt_201501231449_0050_m_000000_0&start=-8193