[置顶] NGINX原理分析之SLAB分配机制
一、基础概述
如果使用伙伴系统分配和释放算法,不仅会造成大量的内存碎片,同时处理效率也比较低。SLAB是一种内存管理机制,其核心思想是预分配。SLAB是将空间按照SIZE对内存进行分类管理的,当申请一块大小为size的内存时,SLAB分配器就从size集合中分配一个单元出去,当释放一个大小为size的内存时,则将其放回到size集合中去,但不是返回给操作系统。当又要申请一个size的内存时,可以重复上面的处理,从而避免了内存碎片的产生。[注:因SLAB处理过程中,涉及的细节太多,在此只是做一个原理上的分析]
二、总体结构
图1 SLAB内存结构
三、处理流程
3.1 初始化流程
typedef struct {
size_t min_size; /* 最小分配单元 */
size_t min_shift; /* 最小分配单元对应的位移 */
ngx_slab_page_t *pages; /* 页数组 */
ngx_slab_page_t free; /* 空闲页链表 */
u_char *start; /* 可分配空间的起始地址 */
u_char *end; /* 可分配空间的结束地址 */
... /* 其他变量成员(省略) */
}ngx_slab_pool_t
代码1 SLAB头部结构体
初始化过程中,对如下数据进行处理:
①、SLOT数组:计算SLOT数组长度、并设置数组成员变量初始数据;
②、PAGES数组:计算PAGES数组长度、并设置数组成员的变量初始数据;
③、可分配空间:按照每页4K的大小,计算可分配空间的页数,不足一页(4K)的空间将会被舍弃;
④、SLAB头:设置其成员变量,如图1中指针所示,其中成员变量free将会指向可分配空间的首地址。
3.2 页的管理
3.2.1 页的分配
1)分配之前
在SLAB初始化之后,所有页可以看成是一个连续的整体,其内存结构如下图所示:
图2 页的结构(分配之前)
2)申请一页
当申请一页时,则将pages[0]从free链表中分离出去,如下图所示:
图3 页的结构(申请一页)
3)申请二页
当再申请二页时,则将page[3]和pages[4]作为一个整体从free链表中分离出去,如下图所示:
图4 页的结构(申请二页)
3.2.2 页的回收
1)回收一页
当页被回收时,被回收的页并不会和未被分配的页进行合并,而是通过链表串联起来,如下图所示:
图5 页的结构(回收一页)
2)回收二页
当页被回收时,被回收的页并不会和未被分配的页进行合并,而是通过链表串联起来,如下图所示:
图6 页的结构(回收二页)
3.4 SLOT的管理
SLOT数组长度N为8,各成员依次负责8(1~8)、16(9~16)、32(17~32)、64(33~64)、128(65~128)、256(129~256)、512(257~512)、1023(513~1023)字节内存块的分配和回收。
SLOT数组各成员相当于链表头,在SLOT的分配和回收过程中,通过链表来组织用于分配各SIZE的PAGE。如,在某时刻,可能存在如下状态:
图7 SLOT和PAGES的关系
3.4.1 页的管理
1)初始状态
在SLAB初始化后,slot链表头的下一个节点都为NULL,如下图所示:
图7 SLOT初始状态
2)添加一页
SLOT[2]负责32(17~32)字节空间的分配和回收,假设现申请分配24字节(17~32之间)的空间,因此将从slot[2]中分配。但在初始状态下slot[2]的下一页为NULL,因此需要向页管理模块申请一页pages[x]内存,再将该页加入到slot[2]的链表中,添加之后的内存结构如下图所示:
图8 slot[2]增加一页
3)暂离链表
SLOT[2]中的每一页有128(4K/32=128)个单元,当一页分配了128次时,表示该页可分配单元分配完毕,此时该页将会暂时从链表中剔除出去,以防止下次申请时,做无效的遍历。如下图所示:
图9 slot[2]第一页被使用完
4)再添一页
当再次申请17~32字节时,此时slot[2]的后续链表为空,因此需要再次向页管理申请一页pages[y]内存,再将该页加入到slot[2]的链表中,如下图所示。如果该页又被分配完,则进行3)的处理。
图10 slot[2]再添一页
5)重入链表
当所有单元被用完的页pages[x]中的一个单元被回收时,页pages[x]中将有1个单元可以再次被分配使用,此时应该将pages[x]重新加入到slot[2]的链表中,以便下次分配时可以从页pages[x]中进行查找。此时内存组织形式如下图所示:
图11 页pages[x]重入链表
6)回收整页
当页pages[x]所有单元被释放后,则该页将会被全部回收:该页将从slot[2]的链表中被剔除,并将页pages[x]重新加入到free链表。此时的内存结构图如下图所示:
图12 回收页pages[x]
3.4.2 SLOT的分配
1)页内结构
被加入到SLOT数组链表的页在逻辑上划分为很多的内存单元,每一小内存单元的使用情况是通过位图进行标记的,1表示被占用,0表示未被占用。如:第20位bit的值为1时,表示第20个内存单元被占用。假如此SLOT链表的PAGE正好可以划分为32块,则其逻辑组织结构如下图所示:
图13 PAGE内结构
2)分配单元
假如此时在SLOT[s]链表的页中连续申请4个内存单元,则其前4个内存单元将首先被占用,则此时的位图结构如下图所示:
图14 分配单元
3)释放单元
假如此时释放SLOT[s]链表页中第3个内存单元,则此时的位图结构如下图所示:
图15 释放单元
—— 邹祁峰
2013.09.15 23:39
[置顶] NGINX原理分析之SLAB分配机制的更多相关文章
- NGINX原理分析 之 SLAB分配机制
1 引言 众所周知,操作系统使用伙伴系统管理内存,不仅会造成大量的内存碎片,同时处理效率也较低下.SLAB是一种内存管理机制,其拥有较高的处理效率,同时也 有效的避免内存碎片的产生,其核心思想是预分配 ...
- [转载]NGINX原理分析 之 SLAB分配机制
作者:邹祁峰 邮箱:Qifeng.zou.job@hotmail.com 博客:http://blog.csdn.net/qifengzou 日期:2013.09.15 23:19 转载请注明来自&q ...
- NGINX原理 之 SLAB分配机制(转)
1 引言 众所周知,操作系统使用伙伴系统管理内存,不仅会造成大量的内存碎片,同时处理效率也较低下.SLAB是一种内存管理机制,其拥有较高的处理效率,同时也有效的避免内存碎片的产生,其核心思想是预分配. ...
- [置顶] Linux Malloc分析-从用户空间到内核空间【转】
转自:http://blog.csdn.net/ordeder/article/details/41654509 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...
- kafka知识体系-kafka设计和原理分析-kafka文件存储机制
kafka文件存储机制 topic中partition存储分布 假设实验环境中Kafka集群只有一个broker,xxx/message-folder为数据文件存储根目录,在Kafka broker中 ...
- [置顶]
长谈:关于 View Measure 测量机制,让我一次把话说完
<倚天屠龙记中>有这么一处:张三丰示范自创的太极剑演示给张无忌看,然后问他记住招式没有.张无忌说记住了一半.张三丰又慢吞吞使了一遍,问他记住多少,张无忌说只记得几招了.张三丰最后又示范了一 ...
- [置顶] 深入探析Java线程锁机制
今天在iteye上提了一个关于++操作和线程安全的问题,一位朋友的回答一言点醒梦中人,至此我对Java线程锁有了更加深刻的认识.在这里也做个总结供大家参考. 先看几段代码吧! 代码一: public ...
- Handler系列之原理分析
上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信 ...
- ECSHOP后台权限分配原理分析
1.在权限管理->管理员列表,中添加一名管理员 2.在admin\includes\inc_menu.php $modules['02_cat_and_goods']['01_goods_lis ...
随机推荐
- 关于已经安装python为何还要安装python-dev
linux发行版通常会把类库的头文件和相关的pkg-config分拆成一个单独的xxx-dev(el)包. 以python为例, 以下情况你是需要python-dev的 你需要自己安装一个源外的pyt ...
- 7.PHP 教程_PHP常量
常量值被定义后,在脚本的其他任何地方都不能被改变. PHP常量 常量是一个简单值的标识符.该值在脚本中不能改变. 一个常量由英文字母.下划线.和数字组成,但数字不能作为首字母出现.(常量名不需要加$修 ...
- windows 7 里面的iis在哪里
我的电脑------控制面板-----卸载程序------打开或关闭WINDOWS功能-----INTERNET信息服务------WEB管理工具下就能找到 给你找图你看看 向左转|向右转
- 利用反馈字段给帝国cms添加留言板功能(图文教程)
帝国cms的插件中提供信息反馈字段,很多人却不会用.这里谢寒教大家如何来给自己的帝国cms网站添加留言板功能 1.找到添加地址 2.添加字段 3.你可以在字段中添加多种字段类型(有文本域,单行文本框, ...
- 转:在控制台中调试AngularJS应用
在控制台中调试AngularJS应用 在创建AngularJS应用时,一个很棘手的问题是如何在Chrome,Firefox,以及IE的JavaScript控制台中访问深藏在应用中的数据和服务.本文将会 ...
- contains 和 ele.compareDocumentPosition确定html节点间的关系
~~~ nodeA.contains(nodeB) //ie , nodeA.compareDocumentPosition(nodeB) //firefox opera 1.DOMElement ...
- ElasticSearch基本用法
最大的特点: 1. 数据库的 database, 就是 index 2. 数据库的 table, 就是 tag 3. 不要使用browser, 使用curl来进行客户端操作. 否则会出现 jav ...
- Liunx 环境下vsftpd的三种实现方法(超详细参数)
以下文章介绍Liunx 环境下vsftpd的三种实现方法 ftp://vsftpd.beasts.org/users/cevans/vsftpd-2.0.3.tar.gz,目前已经到2.0.3版本.假 ...
- MSSQL SERVER 2008 R2 无法连接到数据库,用户sa登录失败,错误:18456
原因:勾选了强制实施密码策略,但是设置的密码很简单依然可以,比如:123456 这是为什么?原来,这个功能要用到NetValidatePasswordPolicy() API这个函数. (该功能只有在 ...
- lwp 模拟行锁堵塞 前端超时
jrhmpt01:/root/async# cat a2.pl use LWP::UserAgent; use utf8; use DBI; use POSIX; use HTTP::Date qw( ...