码迷,mamicode.com
首页 > 其他好文 > 详细

Nginx源码分析(2)-数据结构-ngx_pool_t

时间:2016-04-09 12:18:36      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:

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 }

 

Nginx源码分析(2)-数据结构-ngx_pool_t

标签:

原文地址:http://www.cnblogs.com/wanpengcoder/p/5371208.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!