标签:
1. 数据结构:
//清理回调 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; //当前块指针 }; //内存池数据块 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_pool_large_t *large; //大数据块 ngx_pool_cleanup_t *cleanup; //内存清理 ngx_log_t *log; };
2. 关系简图:
3. 源码注释分析:
1 //创建内存池 2 ngx_pool_t * 3 ngx_create_pool(size_t size, ngx_log_t *log) 4 { 5 ngx_pool_t *p; 6 7 //分配pool内存 8 p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log); 9 if (p == NULL) { 10 return NULL; 11 } 12 13 //设置数据块当分配位置 14 p->d.last = (u_char *) p + sizeof(ngx_pool_t); 15 //设置数据块结束位置 16 p->d.end = (u_char *) p + size; 17 p->d.next = NULL; 18 p->d.failed = 0; 19 20 //设置内存池的最大内存空间 21 size = size - sizeof(ngx_pool_t); 22 p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL; 23 24 //设置current指向当前数据块 25 p->current = p; 26 p->chain = NULL; 27 p->large = NULL; 28 p->cleanup = NULL; 29 p->log = log; 30 31 return p; 32 } 33 34 //销毁内存池 35 void 36 ngx_destroy_pool(ngx_pool_t *pool) 37 { 38 ngx_pool_t *p, *n; 39 ngx_pool_large_t *l; 40 ngx_pool_cleanup_t *c; 41 42 //调用注册的清理函数清理内存 43 for (c = pool->cleanup; c; c = c->next) { 44 if (c->handler) { 45 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, 46 "run cleanup: %p", c); 47 c->handler(c->data); 48 } 49 } 50 51 //释放大块内存 52 for (l = pool->large; l; l = l->next) { 53 54 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc); 55 56 if (l->alloc) { 57 ngx_free(l->alloc); 58 } 59 } 60 61 #if (NGX_DEBUG) 62 63 /* 64 * we could allocate the pool->log from this pool 65 * so we cannot use this log while free()ing the pool 66 */ 67 68 for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { 69 ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0, 70 "free: %p, unused: %uz", p, p->d.end - p->d.last); 71 72 if (n == NULL) { 73 break; 74 } 75 } 76 77 #endif 78 79 //释放内存池结构内存 80 for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { 81 ngx_free(p); 82 83 if (n == NULL) { 84 break; 85 } 86 } 87 } 88 89 //重置内存池 90 void 91 ngx_reset_pool(ngx_pool_t *pool) 92 { 93 ngx_pool_t *p; 94 ngx_pool_large_t *l; 95 96 //释放大块内存 97 for (l = pool->large; l; l = l->next) { 98 if (l->alloc) { 99 ngx_free(l->alloc); 100 } 101 } 102 103 pool->large = NULL; 104 105 //每个数据块均保留头部信息,分配清0 106 for (p = pool; p; p = p->d.next) { 107 p->d.last = (u_char *) p + sizeof(ngx_pool_t); 108 } 109 } 110 111 112 //对齐内存分配 113 void * 114 ngx_palloc(ngx_pool_t *pool, size_t size) 115 { 116 u_char *m; 117 ngx_pool_t *p; 118 119 if (size <= pool->max) { 120 121 p = pool->current; 122 123 do { 124 //找到内存对齐地址位置 125 m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); 126 127 //如果尚有内存未分配,则移动分配指针,返回分配地址 128 if ((size_t) (p->d.end - m) >= size) { 129 p->d.last = m + size; 130 131 return m; 132 } 133 134 //没有可分配内存则继续找下一个数据块 135 p = p->d.next; 136 137 } while (p); 138 139 //查找空余数据块失败,则分配新数据块 140 return ngx_palloc_block(pool, size); 141 } 142 143 //超过内存池限制则动态分配大块内存 144 return ngx_palloc_large(pool, size); 145 } 146 147 //非对齐分配内存 148 void * 149 ngx_pnalloc(ngx_pool_t *pool, size_t size) 150 { 151 u_char *m; 152 ngx_pool_t *p; 153 154 //同样循环查找各个数据块的可用内存 155 if (size <= pool->max) { 156 157 p = pool->current; 158 159 do { 160 m = p->d.last; 161 162 if ((size_t) (p->d.end - m) >= size) { 163 p->d.last = m + size; 164 165 return m; 166 } 167 168 p = p->d.next; 169 170 } while (p); 171 172 //分配新的数据块 173 return ngx_palloc_block(pool, size); 174 } 175 176 //分配大数据块 177 return ngx_palloc_large(pool, size); 178 } 179 180 //分配数据块 181 static void * 182 ngx_palloc_block(ngx_pool_t *pool, size_t size) 183 { 184 u_char *m; 185 size_t psize; 186 ngx_pool_t *p, *new, *current; 187 188 //取得内存池大小 189 psize = (size_t) (pool->d.end - (u_char *) pool); 190 191 //对齐分配内存 192 m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); 193 if (m == NULL) { 194 return NULL; 195 } 196 197 //设置标记 198 new = (ngx_pool_t *) m; 199 200 new->d.end = m + psize; 201 new->d.next = NULL; 202 new->d.failed = 0; 203 204 //跳过头部,对齐内存,分配内存,设置标记 205 m += sizeof(ngx_pool_data_t); 206 m = ngx_align_ptr(m, NGX_ALIGNMENT); 207 new->d.last = m + size; 208 209 //如果前面数据块已经失败5次了 则后续不在查找这些数据块的可用内存了 210 current = pool->current; 211 212 for (p = current; p->d.next; p = p->d.next) { 213 if (p->d.failed++ > 4) { 214 current = p->d.next; 215 } 216 } 217 218 //数据块加入到链表 219 p->d.next = new; 220 221 //设置current查找内存开始块 222 pool->current = current ? current : new; 223 224 return m; 225 } 226 227 //分配大块数据内存 228 static void * 229 ngx_palloc_large(ngx_pool_t *pool, size_t size) 230 { 231 void *p; 232 ngx_uint_t n; 233 ngx_pool_large_t *large; 234 235 p = ngx_alloc(size, pool->log); 236 if (p == NULL) { 237 return NULL; 238 } 239 240 n = 0; 241 242 //查找大内存卡链接位置 243 for (large = pool->large; large; large = large->next) { 244 if (large->alloc == NULL) { 245 large->alloc = p; 246 return p; 247 } 248 249 //如果3次没找到结尾则跳出新建一个放在头部 250 if (n++ > 3) { 251 break; 252 } 253 } 254 255 //分配大内存头部,连接数据,加入到链表 256 large = ngx_palloc(pool, sizeof(ngx_pool_large_t)); 257 if (large == NULL) { 258 ngx_free(p); 259 return NULL; 260 } 261 262 large->alloc = p; 263 large->next = pool->large; 264 pool->large = large; 265 266 return p; 267 } 268 269 //按照指定内存对齐分配大数据块内存,加入到大块内存链表首部 270 void * 271 ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment) 272 { 273 void *p; 274 ngx_pool_large_t *large; 275 276 //分配内存 277 p = ngx_memalign(alignment, size, pool->log); 278 if (p == NULL) { 279 return NULL; 280 } 281 282 //分配大块内存头部 283 large = ngx_palloc(pool, sizeof(ngx_pool_large_t)); 284 if (large == NULL) { 285 ngx_free(p); 286 return NULL; 287 } 288 289 //加入到链表 290 large->alloc = p; 291 large->next = pool->large; 292 pool->large = large; 293 294 return p; 295 } 296 297 //大内存块释放 298 ngx_int_t 299 ngx_pfree(ngx_pool_t *pool, void *p) 300 { 301 ngx_pool_large_t *l; 302 303 for (l = pool->large; l; l = l->next) { 304 if (p == l->alloc) { 305 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, 306 "free: %p", l->alloc); 307 ngx_free(l->alloc); 308 l->alloc = NULL; 309 310 return NGX_OK; 311 } 312 } 313 314 return NGX_DECLINED; 315 } 316 317 //分配内存并初始化为0 318 void * 319 ngx_pcalloc(ngx_pool_t *pool, size_t size) 320 { 321 void *p; 322 323 p = ngx_palloc(pool, size); 324 if (p) { 325 ngx_memzero(p, size); 326 } 327 328 return p; 329 } 330 331 //添加清理函数 332 ngx_pool_cleanup_t * 333 ngx_pool_cleanup_add(ngx_pool_t *p, size_t size) 334 { 335 ngx_pool_cleanup_t *c; 336 337 c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t)); 338 if (c == NULL) { 339 return NULL; 340 } 341 342 //根据size判断是否需要在此为data分配内存空间 343 if (size) { 344 c->data = ngx_palloc(p, size); 345 if (c->data == NULL) { 346 return NULL; 347 } 348 349 } else { 350 c->data = NULL; 351 } 352 353 c->handler = NULL; 354 c->next = p->cleanup; 355 356 p->cleanup = c; 357 358 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c); 359 360 return c; 361 }
标签:
原文地址:http://www.cnblogs.com/wanpengcoder/p/5371208.html