现在的位置: 首页 > 综合 > 正文

简易分析myicq的内存池模型

2013年08月15日 ⁄ 综合 ⁄ 共 8594字 ⁄ 字号 评论关闭

myicq 1.0中实现了一个内存池的模型,可以自动分配和回收对象内存。下面看下其实现方式。

 

首先内存池使用了双向链表来链接的,链表的实现也就是linux中常见的list_head形式,不过是其自己实现的。

有点不解的是,既然用list_head,如果是在linux实现,可以自己调用linux里内建好的list_head,而且还是C的呢,而不是myicq里自己实现的还是类的形式的。又如果如果说是在windows下,那windows下的vc也有类似的形式如:FILED_OFFSET宏就是这样。

感觉在这里用刻意使用list_head,而又是以类的形式使用,我感觉还不如直接使用stl来得方便,或者说代码阅读性好很多。

 

不多说了,看代码。

myicq里的ListHead

list.h

 

list.cpp

 

这样就实现了一个简单的双向链表,如果对list_head机制不熟的可以看我的文章《深入浅出linux内核源代码之双向链表list_head(上)》
和《

深入浅出linux内核源代码之双向链表list_head(下)
》。

 

下面是一个内存池的实现方式:

slab.h

 

slab.cpp

 

内存池是SLAB结构打头的一个大块内存,里面有多个对象内存快,这些内存快个数在下面的#define IMPLEMENT_SLAB(type, num) 宏中的num来指定个数,每个对象空间前面有个OBJ的结构头部。

SLAB后面是连续的OBJ内存快,SLAB结构里的free指向第一个可使用的对象内存快。在回收内存块时这个free指针会指向回收的这块内存,而这块内存会指向free指向的内存块,形成一个可用内存快链表。而内存快又是以next的形式链接在一起。这种实现形式和SGI的STL的内存池的实现非常相似,具体可以参考侯捷的《内存春秋》里说的,里面说得非常详细易懂!

 

cache类是一个以list_head来链接的双向链表,其链接的是SLAB结构的内存块。

 

#define DECLARE_SLAB(type) 宏用在类中声明一个静态变量static Cache type##_cache;并且里面重新定义了new和delete,以便从内存池中分配和销毁。

#define IMPLEMENT_SLAB(type, num) 宏用来类的定义出定义这个静态变量,type用于制定对象大小,num用于指定分配多少个快

 

下面是类DBRequest中使用了这个内存池:

dbmanager.h

 

 

可以看到在类的最后使用了DECLARE_SLAB(DBRequest)来声明。

并且在dbmanager.cpp中调用IMPLEMENT_SLAB(DBRequest, 16)来实现,可以看到每次分配是16个对象。

如果使用满了,会在获取下一个空余对象空间时,自动在cache里在分配一个slab内存快,然后以list_head的双向链表形式链接起来。

 

抱歉!评论已关闭.