从一句话深入理解Linux重要数据结构的内存分配策略

【源自陈凌潇动态】

    最近研读《Linux内核设计与实现》(第三版),其中有这么一句话:“Linux通过slab容器分配task_struct结构,这样能达到对象复用和缓存着色的目的”。初读很是费解,现在就从这一句话来深入解读一下Linux重要数据结构的内存分配策略。

    笔者初学,望指正。                                                                                  ——导语

【化整为零】

    在理解这句话之前,需要先清楚其中的几个概念。

   (1)task_struct结构

    在Linux 中每一个进程都由task_struct 数据结构来定义。task_struct又被叫做进程控制块 PCB(Process Control Block),是控制进程的唯一也是最有效的手段。当我们调用fork()创建一个进程时,系统会为我们产生一个task_struct数据结构。

    为了达到控制进程的目的,task_struct结构必须包含如下内容:进程状态(State)、进程调度信息、标识符(Identifiers)、进程通信有关信息(IPC)、进程链接信息(Links)、时间和定时器信息(Times and Timers)、文件系统信息(File System)、虚拟内存信息(Virtual Memory)、页面管理信息、对称多处理机(SMP)信息、和处理器相关的环境(上下文)信息(Processor Specific Context)等等(参考地址:http://oss.org.cn/kernel-book/ch04/4.3.htm)。

 

图1:task_struct

   (2)slab容器

    slab是从sun os5.4继承和发展来的Linux操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象(如进程描述符等)。这些对象的大小一般比较小,频繁的内存分配和释放,不仅会造成大量的内存碎片,而且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,从而避免这些内碎片。

    对象高速缓存的组织如下图1示,高速缓存的内存区被划分为多个slab,每个slab由一个或多个连续的页框组成,这些页框中既包含已分配的对象,也包含空闲的对象。

图2:slab容器

    slab分配器使用slab分配算法进行实现并采用空间换时间的方式提高分配效率。实质上,slab容器在试图在几项原则中寻求一种平衡,在cache和object中加入slab分配器,是在时间和空间上的折中方案。

 

   (3)对象复用

    其实对象复用应该分为“对象”、“复用”两个词来理解。这里的对象和面向对象中的“对象”是一个意思,不做赘述。“复用”是一种技术,具体的含义因地制宜,在这里可以具体的理解为是slab分配器对于已分配的对象并不丢弃,而是释放并把它们保存在内存中。这样当以后又要请求新的对象时,就可以从内存直接获取而不用重复初始化。此之谓对象复用。

    通过预分配和重复使用task_struct,可以避免动态分配和释放所带来的资源消耗,从而使得进程创建的速度较快。

 

   (4)缓存着色

    讨论缓存着色要从cache机制说起。整个cache被分为m个cache way,每个cache way有相同数量的cache line。内存中的数据依据自己在内存中的cache line索引[getCacheLineIndex(addr)]只能被放入某一个cache way中相对应的cache line里面。假设已经从地址中提取出cache line的索引i,那么硬件会同时访问所有cache way的第i块cache line,找出一个拥有空闲行i的cache way,随后数据就可以放到这个空闲行中。如果m个cache way中都没有找到空闲的地i行,则启动淘汰策略,淘出一个空行。

图3:cache line写入示意图

    而使用slab的数据结构都是分配和释放频繁的小的数据结构,而且数目很多,比如dentry,如果没有color,他们在内存中相对于页的偏移量很可能相同,则其cache line索引也相同,对于x86这种2way 的cache结构,即使cache size很大,也一样使用率低下。color则将不同slab中的同样的数据结构的地址进行一个偏移,因此这些数据结构的cache line索引就错开了。简言之,对存放的对象进行着色,就是为了防止多个对象映射到相同的高速缓存行,提高cache利用率。

 

【归零为整】

    在理解了上述概念之后,再回过头来看原句:“Linux通过slab容器分配task_struct结构,这样能达到对象复用和缓存着色的目的”。那么这句话的意思总结起来就是——Linux利用slab容器来给体积小但调用频繁的进程描述信息进行内存分配,可以实现对象复用和缓存着色,从而加快进程创建速度并提高cache利用率。

    通过对这句话的分析,也加深了对Linux重要数据结构的内存分配策略的理解。上述仅是本人一家之言,如有错处,望批评指正,共同学习。

陈凌潇

2014/11/01


登录用户可以查看和发表评论, 请前往  登录 或  注册
SCHOLAT.com 学者网
免责声明 | 关于我们 | 用户反馈
联系我们: