memcached源码分析之内存管理 -- Slab Allocator(2)

5 篇文章 0 订阅
4 篇文章 0 订阅

转自:http://slowsnail.com.cn/

Slab Allocator源码分析:

前言:虽然会对slab allocator的所有代码进行注释解说,但是slab allocator的很多代码都是与slab的状态获取相关,那些函数不是我们分析的重点,我们将重点放在其提供的功能性接口上。另外slab allocator存在一个自动平衡的机制,该部分由于牵扯到别的模块,读者如果现在接触可能反而会蒙圈,之后的文章中我将会单独对其进行讲解。这样有利于理清其脉络。

Slab Allocator 的源码结构:

Slabs.h //slab allocator头文件,定义了allocator的外部接口
Slabs.c //slab allocator的接口实现都写在里面
Memcached.h //定义了一些slab模块中用到的宏,以及功能性函数,一些数据结构的声明(不是此处的重点)
Memcached.c //对memcached.h中定义的函数的实现(不是此处的重点)。

实际上memcached.c中的内容远远比上面提及的多得多,单个文件的大小就达到了差不多6000行。但是里面与slab相关的函数很少,用户可以当做slab allocator模块相关的代码文件就位slabs.h、slabs.c即可,之所以将memcached.h、memcached.c也列入其中,是为了让读者真得要自己去找一个函数的话知道去哪里找。

Slab allocator相关的概念以及数据结构:

image008
上图中列出了slabclass在程序代码中的表示,没错它肯定是一个结构体。在它的成员变量中,相信除了slabs与slab_list,list_size,perslab,killing成员以外,其它的成员大家都能够根据说明知道其意义。Killing成员关系到slab allocator的自动平衡这里暂时不做讨论,读者也可以将其直接忽略掉。为了说明剩下的slabs,slab_list,list_size,perslab四个成员属性,需要先介绍一个slab这个概念。

Slab:每一个slab可以当做是一个内存“页”,slabclass每次向系统(调用memory_allocate函数)申请新的chunk组的时候都是以“页”为单位进行的。每当slabclass中chunk集的chunk被请求耗尽的时候,slab allocator都会向系统请求一个“页”的内存,并将该“页”的内存划分为对应大小的chunk,并将这些新获得的chunk加入到chunk集中。

有了slab的概念读者大概可以明白perslab的意义了,没错perslab即指每次请求的“页”中能容纳的chunk数,slabs则记录了该slabclass一共请求的slab“页”的个数,slab_list则存储着所请求的slab的其实地址的数组,list_size标识了slab_list数组的大小。

那么slabclass的结构体是看到了,那么上图中的item结构体又是什么呢?没错!Item结构体便是我们上面一直说到的chunk!途中列出了Item中的3个成员属性,实际上还有别的一些重要属性为列出来,我将会在下一篇博文中专门介绍Items模块,其中会对Item结构体进行详细的介绍,此处我们只需要到Item存在着一个向前指针,一个向后指针,和一个数据块数组。   
由上图读者也可以发现,其实每个slabclass中的chunk集是以双向链表的形式进行组织的!

slab allocator中的函数说明:

slab模块向外部提供的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 定义在slabs.h中的函数声明 */
//初始化,slab模块。limit参数指定了初始分配的内存大小,factor参数指定了slab分配的item的增长因子,prealloc参数用于标示是否对slab中的item进行预先分配。
void slabs_init( const size_t limit, const double factor, const bool prealloc);
//根据(item)对象的大小,返回为其分配内存的slab id unsigned int slabs_clsid(const size_t size);
//从id号slab中分配一个size大小的
item void *slabs_alloc( const size_t size, unsigned int id);
//将ptr指向的size大小内存返回给id号
slab void slabs_free( void *ptr, size_t size, unsigned int id);
//调整id号slab所分配出得内存的大小
void slabs_adjust_mem_requested(unsigned int id, size_t old, size_t ntotal);
获取slab的状态的相关函数
//获取系统的状态,stat_type指定了获取的状态的类型(items,slabs,sizes)
bool get_stats( const char *stat_type, int nkey, ADD_STAT add_stats, void *c);
//获取每种slab的相关状态,包括get,set,hit次数等
void slabs_stats(ADD_STAT add_stats, void *c);
/* 下面的函数涉及到slab allocator得自动管理,介意读者可以先跳过 */
int start_slab_maintenance_thread( void );
void stop_slab_maintenance_thread( void );
enum reassign_result_type { REASSIGN_OK=0, REASSIGN_RUNNING, REASSIGN_BADCLASS, REASSIGN_NOSPARE, REASSIGN_SRC_DST_SAME };
enum reassign_result_type slabs_reassign( int src, int dst);
void slabs_rebalancer_pause( void );
void slabs_rebalancer_resume( void );
slabs.c中的static函数(相当于面向对象中的私有函数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//最后然后调用memory_allocate申请空间最后调用split_slab_page_into_freelist函数将申请到得内存,加入到slab中
static int do_slabs_newslab( const unsigned int id);
//将ptr指向的内存块,返还给到id号slab的空闲链表中,size为ptr的大小
static void do_slabs_free( void *ptr, const size_t size, unsigned int id);
//为slab模块进行预先分配
static void slabs_preallocate ( const unsigned int maxslabs);
//当slab_list用尽的时候,扩增slab的slab_list数组
static int grow_slab_list ( const unsigned int id);
//将ptr指向的内存块,划分到id 号slab的空闲链表中
static void split_slab_page_into_freelist( char *ptr, const unsigned int id);
//从第id号页面上获取一块大小为size的内存,并不验证size与id是否匹配了
static void *do_slabs_alloc( const size_t size, unsigned int id);
//比较nz的前nzlength个字符是否与z的前nzlength个字符相等,相等返回1,不等返回-1
static int nz_strcmp( int nzlength, const char *nz, const char *z);
//获取slabs的状态 static void do_slabs_stats(ADD_STAT add_stats, void *c);
//负责管理内存分配,用于分配内存给slab static void *memory_allocate(size_t size);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值