操作系统或系统管理员预先将内存划分成若干个分区,这些分区在系统运行过程中保持不变。分配内存时,系统会找一个空闲且足够大的分区来满足申请者的需求。如果没有合适的分区,系统可以选择让申请者等待,或者将某个分区的内容换出以腾出空间。这种分配方式可能出现内部碎片,并且限制了对于大内存的需求。 为了减少内部碎片,静态分区可以固定分配特定大小的分区,但这也可能导致不公平的等待现象,以及可能出现较大的内部碎片。最佳适应分配法则试图找到最合适的分区来满足需求,这灵活性较高,但可能导致较大的内部碎片。 静态分区法的内存利用率较低,会产生内部碎片,而且分区的尺寸和数量难以确定。与之相对的是动态分区,它不预先确定分区的大小和数量,而是在实际分配内存时进行分区。这种方法可以减少内部碎片,但也可能导致外部碎片。 伙伴系统是动态分区的一种改进,它将内存分区的大小限定为2的k次幂字节,并平分这些分区,使得分割和合并更加容易,从而减少外部碎片。伙伴系统比静态分区更灵活,不受分区尺寸和数量的限制,同时也比动态分区更规范,不易出现外部碎片。 Linux、Windows、Ucore等操作系统都采用伙伴系统来管理物理内存。伙伴系统将最小尺寸定为1页(4KB),最大尺寸定为1024页。在Linux和Windows中,伙伴系统的最小尺寸也是1页。 在伙伴系统中,内存对象的分配和回收是通过Cache和Slab来管理的。Slab是一种内存分配器,它向伙伴系统申请大页块,然后将其划分成小对象分配出去。当回收这些小对象时,它们可以组合成大的页块并还给伙伴系统。Slab算法可以有效地管理小内存对象的分配和回收,减少内部碎片,并提供更快的分配速度。 Slab算法的管理结构包括Cache管理结构和Slab管理结构。Cache管理结构负责创建和销毁Slab,而Slab管理结构则负责内存对象的分配和释放。每个Cache可以管理多个Slab,它们可以被组织成不同的队列,如全满的、不满的、部分满的、完全满的和完全空闲的队列。 在Slab系统中,内存对象的分配和释放可以通过位图或队列来实现。早期的Linux系统中,每个内存对象尾部都加入一个指针来串联空闲对象,但现在这种方法已经被改进,通过数组和链表来管理空闲对象。 Slab系统还可以通过调整对象的尺寸和页块的大小来减少碎片。例如,如果对象的尺寸与处理器的缓存行大小对齐,可以提高缓存效率。在划分页块时,Slab系统会尽量减少外部碎片。 在Linux中,对象的分配可以通过kmalloc函数实现,而释放则通过kfree函数实现。这些函数会根据对象的大小确定Cache,并从Cache中分配或释放内存对象。



































