Linux(内核和用户态的)动态内存管理

来源:互联网 发布:双色球胆拖计算器算法 编辑:程序博客网 时间:2024/05/19 21:59

http://www.ibm.com/developerworks/cn/linux/l-cn-slub/

内核对象缓冲区管理

Linux 内核在运行过程中,常常会需要经常使用一些内核的数据结构(对象)。例如,当进程的某个线程第一次打开一个文件的时候,内核需要为该文件分配一个称为 file 的数据结构;当该文件被最终关闭的时候,内核必须释放此文件所关联的 file 数据结构。这些小块存储空间并不只在某个内核函数的内部使用,否则就可以使用当前线程的内核栈空间。同时,这些小块存储空间又是动态变化的,不可能像物理内存页面管理使用的 page 结构那样,有多大内存就有多少个 page 结构,形成一个静态长度的队列。而且由于内核无法预测运行中各种不同的内核对象对缓冲区的需求,因此不适合为每一种可能用到的对象建立一个“缓冲池”,因为那样的话很可能出现有些缓冲池已经耗尽而有些缓冲池中却又大量空闲缓冲区的现象。因此,内核只能采取更全局性的方法。

我们可以看出,内核对象的管理与用户进程中的堆管理比较相似,核心问题均是:如何高效地管理内存空间,使得可以快速地进行对象的分配和回收并减少内存碎片。但是内核不能简单地采用用户进程的基于堆的内存分配算法,这是因为内核对其对象的使用具有以下特殊性:

  1. 内核使用的对象种类繁多,应该采用一种统一的高效管理方法。
  2. 内核对某些对象(如 task_struct)的使用是非常频繁的,所以用户进程堆管理常用的基于搜索的分配算法比如First-Fit(在堆中搜索到的第一个满足请求的内存块)和 Best-Fit(使用堆中满足请求的最合适的内存块)并不直接适用,而应该采用某种缓冲区的机制。
  3. 内核对象中相当一部分成员需要某些特殊的初始化(例如队列头部)而并非简单地清成全 0。如果能充分重用已被释放的对象使得下次分配时无需初始化,那么可以提高内核的运行效率。
  4. 分配器对内核对象缓冲区的组织和管理必须充分考虑对硬件高速缓存的影响。
  5. 随着共享内存的多处理器系统的普及,多处理器同时分配某种类型对象的现象时常发生,因此分配器应该尽量避免处理器间同步的开销,应采用某种 Lock-Free 的算法。

如何有效地管理缓冲区空间,长期以来都是一个热门的研究课题。90 年代初期,在 Solaris 2.4 操作系统中,采用了一种称为“slab”(原意是大块的混凝土)的缓冲区分配和管理方法,在相当程度上满足了内核的特殊需求。