免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: dreamice
打印 上一主题 下一主题

Nginx源代码情景分析(3)——Nginx内存管理 [复制链接]

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
21 [报告]
发表于 2011-12-09 15:10 |只看该作者
本帖最后由 seufy88 于 2011-12-09 15:38 编辑

回复 20# dreamice


我想针对下面这一小块说一下我的理解,是在ngx_palloc_block函数里定义的

首先ngx_pool_t的链表中的每一个"node",如果它被指定给用户分配size空间时,没有足够的空间的话,就会把这个分配任务交给它的" next " ,但是pool的current没变
如果"next"也没有足够的空间,还是类推,交给它的下一个
如果遍历下来都没有足够的空间,那么调用ngx_palloc_block

这个函数上半部分就是在生成一个新的ngx_pool_t来存放用户要求的size空间
后半部分就像下面这样,要处理之前上面所有链表中各个ngx_pool_t 节点的failed这个参数。
一开始只有pool这一个节点,后来用户不断的申请空间,链表就”不断“的变长(也可能不变长,看申请的大小而定),每变长一次,链接表所有的节点,它的failed都会自增1,于是存在越久的pool,它的failed 在链接增长到4个时,即发生了3次ngx_palloc_block调用,那么这个pool的current就会指向下一个内存池。
单个内存池满足不了用户申请空间是不会造成failed变化的,只有整个内存池链都不满足才会这样
所以如果一开始pool里有2KB空闲空间,其他的内存池也是比较小的空闲空间的话,而用户又多次申请比较大的空间(假设无须large)就会发生pool的current下移,这样这个2KB空间就可惜了,一直没有被用到。
pool的failed   其他内存池的...
0
1     0
2     1     0
3     2     1     0
4     3     2     1    0

到于为什么是4,想了半天没明白。可能是多次经验所得
  1. current = pool->current;

  2.     for (p = current; p->d.next; p = p->d.next) { //遍历整个链
  3.         if (p->d.failed++ > 4) { //先将这个ngx_pool_t的failed加1,将来只要调用ngx_palloc_block函数都会造成链中所有node的failed自增
  4.             current = p->d.next;
  5.         }
  6.     }
  7.    
  8.     p->d.next = new;   //遍历完后p指向最后一个node,再将刚生成的new”挂载“到最后

  9.     pool->current = current ? current : new;
复制代码
crow_freedom 该用户已被删除
22 [报告]
发表于 2011-12-09 21:51 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
crow_freedom 该用户已被删除
23 [报告]
发表于 2011-12-09 22:17 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
24 [报告]
发表于 2011-12-10 21:02 |只看该作者
回复 22# crow_freedom


   你这么一说,确实是这样.图中有点小错误
只有一个ngx_pool_t结构,这个可以看成是个"头",是由ngx_create_pool函数生成的.
这个头包含ngx_pool_data_t和其他一些信息,之后的内存池都只须拥有"ngx_pool_data_t"这个结构即可,这也是为什么会额外再分成一个ngx_pool_data_t结构体了.同时也就只有一个ngx_pool_large_t的链表了.之前按图中来看的话还以为有多个large链表正困惑着呢.
另外,是我看的不仔细,ngx_palloc_block这个函数并没有生成一个"ngx_pool_t结构",只是生成一个大小和它差不多的"内存空间"

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
25 [报告]
发表于 2011-12-11 09:47 |只看该作者
本帖最后由 seufy88 于 2011-12-11 09:49 编辑

简单地重新做了一个

nginx_pool.jpg (95.86 KB, 下载次数: 61)

nginx_pool.jpg

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
26 [报告]
发表于 2011-12-11 12:10 |只看该作者
回复 25# seufy88


    这图画的不错!

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
27 [报告]
发表于 2011-12-11 22:23 |只看该作者
本帖最后由 seufy88 于 2011-12-11 22:28 编辑

回复 26# dreamice
  1. n = 0;

  2.     for (large = pool->large; large; large = large->next) {
  3.         if (large->alloc == NULL) {
  4.             large->alloc = p;
  5.             return p;
  6.         }

  7.         if (n++ > 3) {
  8.             break;
  9.         }
  10.     }

  11.     large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
  12.     if (large == NULL) {
  13.         ngx_free(p);
  14.         return NULL;
  15.     }

  16.     large->alloc = p;
  17.     large->next = pool->large;
  18.     pool->large = large;
复制代码
nginx在释放大内存块时应该只free掉alloc,而保留ngx_pool_large_t这个结构体"方便"再次使用,因而这里如果第一个,或第二个ngx_pool_large_t结构的alloc是NULL的话就会直接"挂载"大内存块p了吧
n的作用就是这个吧. 但为什么只检查前2个,而不遍历整个large链查找alloc是NULL的呢.

ngx_pool_large.jpg (129.33 KB, 下载次数: 57)

ngx_pool_large.jpg

论坛徽章:
2
巳蛇
日期:2014-10-26 22:38:12天蝎座
日期:2016-01-08 09:25:17
28 [报告]
发表于 2011-12-12 14:39 |只看该作者
支持楼主的工作,并感谢分享。。

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
29 [报告]
发表于 2011-12-13 17:09 |只看该作者
回复 27# seufy88


    他这个地方>3的细节,我猜测是作者故意的,认为检查次数太多浪费太多的检查时间,成功的概率已经不大了,还不如自己分配了来的直接。

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
30 [报告]
发表于 2011-12-13 17:36 |只看该作者
回复 29# dreamice


    large链上不断提供给用户新的大块内存,将来释放的话,就应该会存在很多alloc=NULL的情况的呀。
    没有接触大多,所以这里先留个mark  将来回过来看这一段
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP