先看内存管理的核心数据结构

1.内存是如何组织起来的

当前大多数服务器都是numa架构,在这种架构下,内存被分为多个结点进行管理,比如我的服务器有512G内存,被划分为4个numa结点,每个结点的内存大小等于512/4。当程序申请内存时,CPU优先选择自己结点中的内存进行分配,如果自己结点中没有可用内存,则通过备用结点进行分配。这里的重点是知道内存的管理是以结点为单位的。

每个numa结点下内存又被分为1个或几个zone,zone记录着这片内存区域的内存使用情况,有多少空闲页,有多少脏页,有多少共享页等。内存数据结构模型可以简单用下面这个对象来表述(仅用于表示关系,并非真实的数据结构)


node:{

zone:{

free\_area:{

free\_page\_list[MAX\_ORDER]

}

}

}

2.内存是如何管理的

内存的分配通过2个著名的系统buddy和slab进行。

buddy算法即伙伴算法,将相同数量的内存页通过链表串成一串,申请内存的时候从各个链表上找出与申请匹配度最高的内存并分配出去。相同数量的内存页是指,从2的0次方到10次方个固定数量的页面,可以用过cat /proc/buddyinfo来看自己系统的各空闲块的情况。题外话:记得之前有个程序需要使用大片的连续内存,在服务的时候经常因为内存分配失败而出现异常。当时通过free来看剩余内存的数量是很充足的,但是通过buddyinfo来看剩余的内存,全部都集中在小块的链表里,大块的早就已经被耗尽。后边优化程序,自己维护内存池,不再依赖系统内存,问题解决。

slab分配器,由于buddy系统的分配粒度比较大,在内核频繁申请小内存的场景下内存的浪费情况比较严重。因此,又提出了slab分配器的概念。slab分配器类似于一种cache算法,它工作在buddy的前一层,当内存申请到来时,它会通过buddy申请一块内存叫做slab,并将这一块内存进行更小粒度的分配,更小的粒度叫object,一个slab的大小可以是1个或多个页。系统把给相同object做供给的slab集合到一起进行管理,数据结构叫做kmem\_cache,它维护了3个slab的链表,分别是full,partial,empty,full这条链表上都是已经被用满了的slab,partial是已经有在用,但是没有用完的slab,empty是完全空闲的slab。每个kmem\_cache是一种object的“分配池”,object被释放后,kmem\_cache标记它为空闲并挂到empty上;有请求到来时从partial上找一个空闲的object分配出去,由于省去了底层的申请和释放过程,object的申请释放非常轻量,效率很高。所有的kmem\_cache可以通过cat /proc/slabinfo进行查看

3.分配的内存如何给到用户进程

(待续)

标签: 内存, slab, 运维, 基础知识, 分配, object, 链表, 结点

相关文章推荐

添加新评论,含*的栏目为必填