第一级空间配置器

  第一级配置以malloc(), free(), realloc()等c函数执行实际的内存配置,释放、重配置操作,并实现出类似c++ new handler的机制。它不能直接使用c++ new handler机制,因为它并非使用::operator new来配置内存。

  所谓的c++ new handler机制,就是你可以要求系统在内存配置需求无法被满足时,调用一个你所指定的函数。换句话说,一旦::operator new无法完成任务,在丢出std::bad_alloc异常状态之前,会调用一个由客户端指定的处理例程。该处理例程被称为c++ new handler。new handler解决内存不足的做法有特定的模式。

  //oom指:out of memory

  SGI以malloc而不是::operator new来配置内存,因此SGI不能直接使用C++的set_new_handler(),必须仿真一个类似的set_new_handler()。SGI低一级配置器的allocate()和realloc() 都是在调用malloc()和realloc()不成功之后,改调用oom_malloc()和oom_realloc()。后两者都有内循环,不断调用“内存不足处理例程”,期望在某次调用之后获得足够的内存圆满完成任务。但是如果“内存不足处理例程”并未被客户端设定,oom_malloc()和oom_realloc()便会调用_THROW_BAD_ALLOC,丢出bad_alloc异常信息,或利用二线exit(1)直接终止程序。

第二级空间配置器

  第二级配置器多了一些机制,避免太多小额区块造成内存的碎片。小额区块带来的其实不仅仅是内存碎片,配置时的额外负担(overhead系统开销(计算机网络)overhead,在计算机网络帧结构中,除了有用数据以外,还有很多控制信息,这些控制信息用来保证通信的完成。这些控制信息被称作系统开销。)也是一个大问题。额外负担永远无法避免,毕竟系统要靠这多出来的空间来管理内存。

  SGI第二级配置器的做法是,如果区块够大,超过128bytes时,就移交给第一级配置器处理。当区块小于128bytes时,则以内存池(memory pool)的方式管理,此法又称之为层次配置(sub_allocation):每次配置一大块内存,并维护对应的自由链表(free list)。下次若再有相同大小的内存需求,就直接从free-lists中拨出。如果客户端释放了小额区块,也负责回收。为了方便管理,SGI第二级配置器会主动将任何小区块的内存需求量上调至8的倍数(如需求为30bytes,自动调整为32bytes)。并维护16(128/8=16)个free-lists,各自管理的大小为8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128的小额区块。

  free-lists的结构如下:

union obj{

union obj * free_list_link;

char client_data[1];   /*the client sees this.*/

    }

  大家可能会想为了维护链表,每个节点都需要额外的指针指向下一个节点,这不又造成了另一种额外负担么?但是请注意,上述obj所用的是union,所以从其第一个字段来看,obj可以被当做一个指向形式相同的另一个obj的指针;从第二个字段来看,可以把它看做指向实际区块的指针。

内存分配策略:

叙述之前做一下约定:

req_size ,表示用户请求的内存大小。

_round_up(size_t size),表示对用户请求的内存大小,向上调整为8的倍数。

例如:req_size = 14 , 那么_round_up(req_size ) 的返回值是16。

_pool_watermark(size_t size),表示用户请求的内存在head_list中的下标。

例如:req_size = 14 , 那么_pool_watermark(req_size ) 的返回值是1。

具体策略:
1)如果用户申请超过128字节的内存,则直接调用第一级简单空间配置器;否则,执行2)。

2)小于128bytes就检测对应的free-lists,如果free list之内有可用的区块,就直接返回给用户。如果没有可用区块,就将区块大小上调至8的倍数边界,然后调用refill(),准备为free list重新填充空间。

内存池取空间操作

从内存池中取空间给free
list,是chunk_alloc()的工作。其工作流程如下:

chunk_alloc()中以end_free
– start_free 来判断内存池是的剩余内存。

1, 
如果内存充足,则直接调出20个区块返回给对应的free list。

2, 
如果内存不足,但是end_free – start-free的值仍然大于size,即可以提供一个以上的区块,就提供这不足20的区块出去,这时候pass by reference 的nobjs参数将被修改为实际供应的区块个数。

3, 
如果剩余内存不足提供一个区块,则调用malloc从heap中分配内存给内存池。

  a) 如果heap足够,则分配20*2+n(n为附加量,随着分配次数的增加而增加)的内存块给内存池,其中第一个给用户,19个给free list维护,剩余的20+n个给内存池维护。

  b) 如果heap也没了,malloc失败,chunk alloc()就搜寻整儿free list看是否有“尚未利用的区块,且区块足够大”,如果有则分配给用户。

  c) 如果没搜寻到,则调用第一级空间配置器。第一级空间配置器也采用的是malloc,但是第一级空间配置器有out of memory处理机制(类似new handler处理机制),或许有机会释放出内存,如果可以就成功,否则抛出bad_alloc异常。

内存释放策略

如果释放的内存超过128字节,则调用“简单空间配置器”的内存释放函数。否则,找出对应的free list,将区块收回。

[stl] SGI STL的空间配置器的更多相关文章

  1. STL源码剖析 — 空间配置器(allocator)

    前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配 ...

  2. STL源码剖析(空间配置器)

    前言 在STL中,容器的定义中都带一个模板参数,如vector template <class T, class Alloc = alloc> class vector {...} 其中第 ...

  3. STL学习笔记:空间配置器allocator

    allocator必要接口: allocator::value_type allocator::pointer allocator::const_pointer allocator::referenc ...

  4. STL源码剖析——空间配置器Allocator#1 构造与析构

    以STL的运用角度而言,空间配置器是最不需要介绍的东西,因为它扮演的是幕后的角色,隐藏在一切容器的背后默默工作.但以STL的实现角度而言,最应该首先介绍的就是空间配置器,因为这是这是容器展开一切运作的 ...

  5. STL源码剖析——空间配置器Allocator#2 一/二级空间配置器

    上节学习了内存配置后的对象构造行为和内存释放前的对象析构行为,在这一节来学习内存的配置与释放. C++的内存配置基本操作是::operator new(),而释放基本操作是::operator del ...

  6. STL源码剖析——空间配置器Allocator#3 自由链表与内存池

    上节在学习第二级配置器时了解了第二级配置器通过内存池与自由链表来处理小区块内存的申请.但只是对其概念进行点到为止的认识,并未深入探究.这节就来学习一下自由链表的填充和内存池的内存分配机制. refil ...

  7. STL源码分析读书笔记--第二章--空间配置器(allocator)

    声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...

  8. STL——空间配置器(构造和析构基本工具)

    以STL的运用角度而言,空间配置器是最不需要介绍的东西,它总是隐藏在一切组件(更具体地说是指容器,container)的背后,默默工作,默默付出.但若以STL的实现角度而言,第一个需要介绍的就是空间配 ...

  9. STL 之 空间配置器(allocator)

    一.SGI 标准的空间配置器,std::allocator SGI也定义了一个符合部分标准,名为allocator的配置器,但是它自己不使用,也不建议我们使用,主要原因是效率不佳. 它只是把C++的操 ...

  10. STL——空间配置器(SGI-STL)

    一. 空间配置器标准接口 参见<STL源码剖析>第二章-2.1.<memory>文件. 二.具备次配置力的SGI空间配置器 1. SGI STL的配置器与众不同,也与标准规范不 ...

随机推荐

  1. Java框架篇---Mybatis 入门

    一.Mybatis介绍 MyBatis是一款一流的支持自定义SQL.存储过程和高级映射的持久化框架.MyBatis几乎消除了所有的JDBC代码,也基本不需要手工去设置参数和获取检索结果.MyBatis ...

  2. 【原创】MYSQL++源码剖析——前言与目录

    终于完成了! 从第一次想写到现在真的写好大概花了我3个月时间.原来一直读人家的系列文章,总感慨作者的用心良苦和无私奉献,自己在心里总是会觉得有那么些冲动也来写一个. 最开始的麻烦是犹豫该选哪个主题.其 ...

  3. MyBatis知多少(15)数据模型

    瘦数据模型是一种最为臭名昭著并且问题多多的对关系数据库系统的滥用.不幸的是,有时又的确需要瘦数据模型.所谓瘦数据模型,就是简单地将每张表都设计为一种通用数据结构,用于存储名值对的集合.这非常像Java ...

  4. MFC ADO连接Oracle12c数据库 服务端配置

    要想客户端访问服务器端的oracle数据库的话,还需要服务端设置下监听程序及本地网络服务名配置. 发现百度文库上面有这方面的文档,我就不重复写了.请参照一下网址: http://wenku.baidu ...

  5. 8月11日嵌入式Linux开发免费项目体验邀您参与

    嵌入式Linux开发免费项目体验开课啦~~我们特意邀请到粤嵌金牌讲师和技术专家,为大家带来精彩有趣的嵌入式公开课,涉及到嵌入式学习.研发的方方面面.课堂中我们能体验到的不仅仅是最新资讯.技术体验,还有 ...

  6. [OpenCV] Image Processing - Image Elementary Knowledge

    "没有坚实的理论基础,实践只会浅尝于表面." 这是两本打基础的书,没系统学过的话,怎么好意思说自己会CV. 该领域,兴军亮 这个名字屡次出现,看来是计算机视觉领域国内的年轻才俊,向 ...

  7. Mysql学习笔记(三)运算符和控制流函数

    本章学习内容: 1.操作符 2.控制流程函数 操作符: i.圆括号.. 简单的介绍一下圆括号,圆括号的使用的目的是规定计算表达式的顺序...这个想必大家都熟悉例如  mysql>select 1 ...

  8. [ORM] Entity Framework(2) CodeFirst进阶

    在上一节中,实现了CodeFirst快速入门.但是很多与数据库的细节还无法自定义.以及使用EF过程中,需要注意的事项. 在本节中,会涉及到以下 EF中的连接字符串 EF的对象状态 延迟加载,为什么需要 ...

  9. jsckson,想说爱你不容易啊。。。406错误

    最近使用spring4.0的Mvc,json请求时,客户端报错,406 Not Acceptable 解决方法一: 1.导入第三方的jackson包,jackson-mapper-asl-1.9.7. ...

  10. .Net一般处理程序来实现用户名的验证

    一般处理程序 在说一般处理程序之前,先来看看什么是aspx.在vs中,使用的大多是aspx页面.aspx页面就是在接收到一个请求之后,将返回的结果生成一个html页面返回给服务器.当我们有时候需要自己 ...