貌似2013年写的技术文章只有个位数,实在是不应该啊! 最近几天看了些Linux Kernel的内存管理,就写点东西吧。

我们知道Linux内核内存管理最底层的是伙伴系统,伙伴系统解决是的内存外碎片问题,而不能解决内碎片问题,因此在伙伴系统之上,有Slub/Slab/Slob 三种内存分配策略(有的书上叫高速缓存,我个人很不喜欢这个名字,因为很容易与硬件的高速缓存TLB混淆),不过内核同时只能使用这三种中的一种,Slub 是现在内核默认的选项,无论是我们安装在自己电脑上的Linux系统,还是运行在服务器上的系统,都是用的Slub; Slab 作为鼻祖曾经辉煌一时,现在退居二线了; Slob 则是主要用于内存非常小的嵌入式系统,只有在编译内核的时候配置了 Embedded System 选项,才可以选择使用Slob。

Slob的源代码只有600行左右,与 Slub/Slab 动辄6000行的代码相比要简洁的多,所以像我这样的初学者,选择Slob下手应该容易一点。

先来介绍一下Slob的基本思路吧。 我们知道通常计算机的内存是以页(Page)为管理单位的,一般一个Page是 4KB,每一个Page都会有一个对应的结构体 struct page 来描述它,保存了它的各种信息。 Slob就是以一个Page为基础的,当申请小于一个Page大小的内存时,Slob会为你找到一个合适位置,而当你申请一块大于4KB的内存时,Slob直接交给伙伴系统去处理。

Slob 有3个空闲块的链表,分别是 free_slob_small free_slob_mediumfree_slob_large
对于小于256字节的对象,将从free_slob_small链表中分配;
对于小于1024字节的对象,将从free_slob_medium链表中分配;
对于大于1024字节的对象,将从free_slob_large链表中分配;
对于大于PAGE_SIZE的对象,将直接通过伙伴系统分配。

值得注意的是,与Slub/Slab不同,Slob的每个页中可以保存不同大小的对象,基本上就是如下图这样。

图中红色的块代表已经被使用的,蓝色的是还没有被分配的。对Slob有一个大概的认识以后,我们再来看看它的数据结构。我发现在看源代码的过程中,先把数据结构理解了会很有帮助,有的函数一看到名字就能猜出是干什么的。

Slob的结构体在哪呢? 如果你在mm/slob.c里面找是根本找不到的,它被嵌在了struct page结构体里面,在include/linux/mm_types.h中。

Linux内核源码真的是把C语言运用到了极致,而且为了提高内存利用率,内核从来都是榨干每一个bit,不过….代价就是太TM晦涩难懂啦!!
我们先来看看struct page吧,page结构中用了很多联合体(union), 这样做的目的是一个存储单元可以提供不同的用途,把一些多余的信息以及一些#ifdefine去掉以后,大致是这个样子:

C语言:
01 struct {
02     union {
03         pgoff_t index;
04         void *freelist;
05         bool pfmemalloc;
06     };
07 
08     union {
09         unsigned long counters;
10         struct {
11         union {
12             atomic_t _mapcount;
13             struct { /* SLUB */
14             unsigned inuse:16;
15             unsigned objects:15;
16             unsigned frozen:1;
17             };
18             int units;
19             };
20             atomic_t _count;
21         };
22     };
23 };
24 
25 union {
26     struct list_head lru;
27     struct {
28         struct page *next;
29         int pages;
30         int pobjects;
31     };
32     struct list_head list;
33     struct slab *slab_page;
34     };

Slob真正用到的只有3个变量:freelistunitslist;也就是说,如果内核中有struct slob这个结构体的话,那么它应当是这样的:

struct slob {
void *freelist;
int units;
struct list_head list;
};
由此可见,Slob是一种非常简单的分配策略,在下一篇博客中,我们再来详细的介绍Slob的实现。

参考资料:
【1】http://blog.csdn.net/vanbreaker/article/details/7705202
【2】http://lwn.net/Articles/565097/

【3】Paper : A Heap of Trouble: Breaking the Linux Kernel SLOB Allocator

13,913 views
Home

6 Comments so far

Trackbacks/Pingbacks

Leave a comment

Name(required)
Mail (required),(will not be published)
Website(recommended)

Fields in bold are required. Email addresses are never published or distributed.

Some HTML code is allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
URLs must be fully qualified (eg: http://blog.nlogn.cn),and all tags must be properly closed.

Line breaks and paragraphs are automatically converted.

Please keep comments relevant. Off-topic, offensive or inappropriate comments may be edited or removed.