1 引言

众所周知,操作系统使用伙伴系统管理内存,不仅会造成大量的内存碎片,同时处理效率也较低下。SLAB是一种内存管理机制,其拥有较高的处理效率,同时也有效的避免内存碎片的产生,其核心思想是预分配。其按照SIZE对内存进行分类管理的,当申请一块大小为SIZE的内存时,分配器就从SIZE集合中分配一个内存块(BLOCK)出去,当释放一个大小为SIZE的内存时,则将该内存块放回到原有集合,而不是释放给操作系统。当又要申请相同大小的内存时,可以复用之前被回收的内存块(BLOCK),从而避免了内存碎片的产生。[注:因SLAB处理过程的细节较多,在此只是做一个原理上的讲解]

 

2 总体结构

图1 SLAB内存结构

3 处理流程

  如图1中所示:SLAB管理机制将内存大体上分为SLAB头、SLOT数组、PAGES数组、可分配空间、被浪费空间等模块进行分别管理,其中各模块的功能和作用:
  • SLAB头:包含SLAB管理的汇总信息,如最小分配单元(min_size)、最小分配单元对应的位移(min_shift)、页数组地址(pages)、空闲页链表(free)、可分配空间的起始地址(start)、内存块结束地址(end)等等信息(如代码1所示),在内存的管理过程中,内存的分配、回收、定位等等操作都依赖于这些数据。
  • SLOT数组:SLOT数组各成员分别负责固定大小的内存块(BLOCK)的分配和回收。在nginx中SLOT[0]~SLOT[7]分别负责区间在[1~8]、[9~16]、[17~32]、[33~64]、[65~128]、[129~256]、[257~512]、[513~1024]字节大小内存的分配,但为方便内存块(BLOCK)的分配和回收,每个内存块(BLOCK)的大小为各区间的上限(8、16、32、64、128、256、512、1024)。比如说:假如应用进程请求申请5个字节的空间,因5处在[1~8]的区间内,因此由SLOT[0]负责该内存的分配,但区间[1~8]的上限为8,因此即使申请5个字节,却依然分配8字节给应用进程。以此类推:假如申请12字节,12处于区间[9~16]之间,取上限16,因此由SLOT[1]分配16个字节给应用进程;假如申请50字节,50处于区间[33~64]之间,取上限64,因此由SLOT[2]分配64个字节给应用进程;假如申请84字节,84处于区间[65~128]之间,取上限128,因此由SLOT[3]分配128个字节;...;假如申请722字节,722处于区间[513~1024]之间,取上限1024,因此由SLOT[7]分配1024字节。
  • PAGES数组:PAGES数组各成员分别负责可分配空间中各页的查询、分配和回收,其处理流程可参考3.2节的说明。
  • 可分配空间:SLAB在逻辑上将可分配空间划分成M个内存页,每页大小为4K。每页内存与PAGES数组成员一一对应,由PAGES数组各成员负责各内存页的分配和回收。
  • 被浪费空间:按照每页4K的大小对空间进行划分时,满足4K的空间,将作为可分配空间被PAGES数组进行管理,而最后剩余的不足4K的内存将会被舍弃,也就是被浪费了!

3.1 初始化流程

初始化阶段主要完成对SLOT头、SLOT数组、PAGES数组、可分配空间和被浪费空间的区域分化,各区域的划分可参考图1和各模块功能的说明。nginx中slab结构体如下所示:

  1. typedef struct {
  2. size_t            min_size;     /* 最小分配单元 */
  3. size_t            min_shift;    /* 最小分配单元对应的位移 */
  4. ngx_slab_page_t  *pages;        /* 页数组 */
  5. ngx_slab_page_t   free;         /* 空闲页链表 */
  6. u_char           *start;        /* 可分配空间的起始地址 */
  7. u_char           *end;          /* 内存块的结束地址 */
  8. ...                             /* 其他变量成员(省略) */
  9. }ngx_slab_pool_t

代码1 SLAB头部结构体

3.2 页的管理

3.2.1 页的分配

1)分配之前

在SLAB初始化之后,所有页可以看成是一个连续的整体,其内存结构如下图所示:

图2 页的结构(分配之前)

2)申请一页

当申请一页时,则将pages[0]从free链表中分离出去,如下图所示:

图3 页的结构(申请一页)

3)申请二页

当再申请二页时,则将page[3]和pages[4]作为一个整体从free链表中分离出去,如下图所示:

图4 页的结构(申请二页)

3.2.2 页的回收

1)回收一页

当页被回收时,被回收的页并不会和未被分配的页进行合并,而是通过链表串联起来,这样将造成运行的时间越长,要申请到超过一页大小的空间也会变得越来越难。正是因为这个原因,所以slab机制不适合用来反复分配和回收超过一页大小的内存空间。如下图所示:[切记:slab机制不适合用来反复分配和回收超过一页大小的内存空间]

图5 页的结构(回收一页)

2)回收二页

当页被回收时,被回收的页并不会和未被分配的页进行合并,而是通过链表串联起来,如下图所示:

图6 页的结构(回收二页)

3.4 SLOT的管理

SLOT数组的作用可以参考第三章开头的阐述。SLOT数组各成员相当于链表头,在SLOT的分配和回收过程中,通过链表来组织用于分配各SIZE(1~1024)的PAGE。如,在某时刻,可能存在如下状态:

图7  SLOT和PAGES的关系

3.4.1 页的管理

1)初始状态

在SLAB初始化后,slot链表头的下一个节点都为NULL,如下图所示:

图8 SLOT初始状态

2)添加一页

SLOT[2]负责32(17~32)字节空间的分配和回收,假设现申请分配24字节(17~32之间)的空间,因此将从slot[2]中分配。但在初始状态下slot[2]的下一页为NULL,因此需要向页管理模块申请一页pages[x]内存,再将该页加入到slot[2]的链表中,添加之后的内存结构如下图所示:

图9 slot[2]增加一页

3)暂离链表

SLOT[2]中的每一页有128(4K/32=128)个单元,当一页分配了128次时,表示该页可分配单元分配完毕,此时该页将会暂时从链表中剔除出去,以防止下次申请时,做无效的遍历。如下图所示:

图10 slot[2]第一页被使用完

4)再添一页

当再次申请17~32字节时,此时slot[2]的后续链表为空,因此需要再次向页管理申请一页pages[y]内存,再将该页加入到slot[2]的链表中,如下图所示。如果该页又被分配完,则进行3)的处理。

图11 slot[2]再添一页

5)重入链表

当所有单元被用完的页pages[x]中的一个单元被回收时,页pages[x]中将有1个单元可以再次被分配使用,此时应该将pages[x]重新加入到slot[2]的链表中,以便下次分配时可以从页pages[x]中进行查找。此时内存组织形式如下图所示:

图12 页pages[x]重入链表

6)回收整页

当页pages[x]所有单元被释放后,则该页将会被全部回收:该页将从slot[2]的链表中被剔除,并将页pages[x]重新加入到free链表。此时的内存结构图如下图所示:

图13 回收页pages[x]

3.4.2 SLOT的分配

1)页内结构

被加入到SLOT数组链表的页在逻辑上划分为很多的内存单元,每一小内存单元的使用情况是通过位图进行标记的,1表示被占用,0表示未被占用。如:第20位bit的值为1时,表示第20个内存单元被占用。假如此SLOT链表的PAGE正好可以划分为32块,则其逻辑组织结构如下图所示:

图14 PAGE内结构

2)分配单元

假如此时在SLOT[s]链表的页中连续申请4个内存单元,则其前4个内存单元将首先被占用,则此时的位图结构如下图所示:

图15 分配单元

3) 释放单元

假如此时释放SLOT[s]链表页中第3个内存单元,则此时的位图结构如下图所示:

图16 释放单元

转自:"祁峰"的CSDN博客

NGINX原理 之 SLAB分配机制(转)的更多相关文章

  1. NGINX原理分析 之 SLAB分配机制

    1 引言 众所周知,操作系统使用伙伴系统管理内存,不仅会造成大量的内存碎片,同时处理效率也较低下.SLAB是一种内存管理机制,其拥有较高的处理效率,同时也 有效的避免内存碎片的产生,其核心思想是预分配 ...

  2. [转载]NGINX原理分析 之 SLAB分配机制

    作者:邹祁峰 邮箱:Qifeng.zou.job@hotmail.com 博客:http://blog.csdn.net/qifengzou 日期:2013.09.15 23:19 转载请注明来自&q ...

  3. [置顶] NGINX原理分析之SLAB分配机制

    一.基础概述 如果使用伙伴系统分配和释放算法,不仅会造成大量的内存碎片,同时处理效率也比较低.SLAB是一种内存管理机制,其核心思想是预分配.SLAB是将空间按照SIZE对内存进行分类管理的,当申请一 ...

  4. memcached学习——memcached的内存分配机制Slab Allocation、内存使用机制LRU、常用监控记录(四)

    内存分配机制Slab Allocation 本文参考博客:https://my.oschina.net/bieber/blog/505458 Memcached的内存分配是以slabs为单位的,会根据 ...

  5. Linux内存分配机制之伙伴系统和SLAB

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6539590.html  内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生.这就要求 ...

  6. memcached内存分配机制

    memcached的内存分配没有用到c语言中自带的malloc函数,因为这个函数分配内存的时候效率很低,对于这种要求快速响应,对效率要求非常高的缓存软件来说非常不合适. memcached用的是自己的 ...

  7. 深入理解PHP之:Nginx 与 FPM 的工作机制

    网络上有很多关于如何配置 Nginx + FPM 的文章,但它们更多从操作的角度出发,告诉我们怎么做,但却没有告诉我们为什么要这么做,本文从 Nginx 与 FPM 的工作机制出发,探讨配置背后的原理 ...

  8. Memcache简介 & 内存分配机制

            关于这个东西里面到底应该存放数据网上一直有很多种说法,有的说sql进行md5之后作为键值,结果作为内容存放,也有人说按照业务逻辑错放,反正是炒的不亦乐乎.        本人经过将近2 ...

  9. PHP5底层原理之垃圾回收机制

    概念 垃圾回收机制 是一种内存动态分配的方案,它会自动释放程序不再使用的已分配的内存块. 垃圾回收机制 可以让程序员不必过分关心程序内存分配,从而将更多的精力投入到业务逻辑. 与之相关的一个概念,内存 ...

随机推荐

  1. A profile to detect when a SMS database has been changed

    http://webmail.dev411.com/t/gg/tasker/12bdddbsak/a-profile-to-detect-when-a-sms-has-been-sent A bela ...

  2. Oracle中NVARCHAR2与VARCHAR2的相互转换

    将NVARCHAR2转换为VARCHAR2: declare v_username   varchar2(12)   ; v_nm_login   nvarchar2(12); begin selec ...

  3. hdu1238 Substrings (暴力)

    http://acm.hdu.edu.cn/showproblem.php?pid=1238 Substrings Time Limit : 2000/1000ms (Java/Other)   Me ...

  4. 【spring boot】spring boot后台时间正确,返回给前台的时间不正确,和后台差8个小时

    后台打印的时间如下: 数据库存储时间如下: 接口返回给前台的时间如下: 相差8个小时. 原因如下: spring-boot中对于@RestController或者@Controller+@Respon ...

  5. .NET:通过 CAS 来理解数据库乐观并发控制,顺便给出无锁的 RingBuffer。

    背景 大多数企业开发人员都理解数据库乐观并发控制,不过很少有人听说过 CAS(我去年才听说这个概念),CAS 是多线程乐观并发控制策略的一种,一些无锁的支持并发的数据结构都会使用到 CAS,本文对比 ...

  6. cocos2d-x 3.0 事件处理

    參考文章: star特530的CSDN博客:http://blog.csdn.net/star530/article/details/18325493 https://github.com/chuko ...

  7. 关于OpenLDAPAdmin管理页面提示“This base cannot be created with PLA“问题. Strong Authentication Required问题

    经过查询,最终总结和处理如下: 1.首先需要在/etc/openldap/目录下,创建一个base.ldif文件,如下所示: 2.在base.ldif文件中,写入如下信息,为创建初始化根节点做准备工作 ...

  8. 分享JavaScript获取网页关闭与取消关闭的事件

    在做Web开发时,我们经常用到页面关闭事件onbeforeunload,可以给用户一个选择放弃关闭的机会,就比如这个博客编辑器.如果用户选择了离开,那么onunload事件自然会触发:但若用户选择了取 ...

  9. TCP的三次握手与四次挥手(详解+动图)

    背景描述 通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之间的通信.但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进程在 ...

  10. 数学图形之SineSurface与粽子曲面

    SineSurface直译为正弦曲面.这有可能和你想象的正弦曲线不一样.如果把正弦曲线绕Y轴旋转,得到的该是正弦波曲面.这个曲面与上一节中的罗马曲面有些相似,那个是被捏过的正四面体,这个则是个被捏过正 ...