【操作系统】内存管理: Buddy算法与Slab算法详解

内存管理算法:Buddy算法与Slab算法详解

内存管理是操作系统核心功能之一,直接影响系统性能和稳定性。Buddy算法Slab算法是两种经典的内存管理策略,分别适用于不同场景。以下是它们的对比分析:


1. Buddy算法(伙伴系统)

1.1 核心思想

  • 多层级块共存。将内存划分为 大小相等的块(如 2^n KB),并通过 递归拆分/合并 管理空闲内存。
    Buddy系统会 ​同时维护多种大小的内存块​(例如:16KB、8KB、4KB、2KB、1KB),构成一个分层的块大小体系。所有块大小都是2的幂次方(2^n)。
  • 适合管理 物理内存页(如Linux的 zone allocator)。

1.2 工作原理

  1. 初始化:内存被划分为最大可能的 2^n 块(如4MB)。
  2. 分配内存
    • 如果请求大小 ≤ 当前块大小,则 拆分 为两个"伙伴"块(如1MB → 2×512KB)。
    • 重复拆分直到找到合适大小的块。
  3. 释放内存
    • 释放的块会检查其"伙伴"是否空闲。
    • 如果伙伴空闲,则 合并 为更大的块。

1.3 示例

  • 分配时
    从最接近需求大小的层级开始查找,若没有合适块,则 将大块逐级拆分
    示例:请求3KB内存的流程

    初始状态:仅有一个16KB空闲块  
    步骤1:16KB → 拆分为2×8KB  
    步骤2:8KB  → 拆分为2×4KB  
    结果:分配1个4KB块(实际分配4KB,内部碎片1KB【浪费】)
    
  • 释放时
    检查相邻的"伙伴块"是否空闲,若空闲则 合并为更大的块
    示例:释放两个相邻4KB块

    释放4KB块A → 检查伙伴块B是否空闲 → 是 → 合并为8KB  
    若8KB的伙伴也空闲 → 继续合并为16KB
    

1.4 关键结论

  1. 同时存在多种块大小

    • 系统中会 同时存在不同层级的块(如16KB、8KB、4KB等)。
    • 块大小取决于当前分配/释放的请求模式。
  2. 分配策略导致内部碎片

    • 即使请求3KB,也会分配4KB(最小满足2^n的块)。
    • 这是Buddy算法的主要缺点之一。
  3. 合并机制减少外部碎片

    • 通过合并伙伴块,尽可能恢复大块内存,避免长期碎片化。

优点

  • 避免外部碎片:通过合并机制减少碎片。
  • 快速分配/释放:O(log n) 时间复杂度。

缺点

  • 内部碎片:分配大小必须为 2^n,可能浪费内存(如申请3KB实际分配4KB)。
  • 不适合小内存:频繁拆分/合并影响性能。

1.5 对比其他算法

特性Buddy算法SLAB分配器
块大小动态变化的2^n块固定大小的对象块
碎片类型内部碎片(浪费在2^n对齐)无碎片(对象大小精确匹配)
适用场景物理页/大块内存管理高频小对象分配

1.6 实际应用案例

  • Linux内核:Buddy管理物理页(4KB/8KB等),SLAB管理小对象。
  • 嵌入式系统:在MMU-enabled设备中用于大内存分配(如RT-Thread Smart)。

总结:Buddy算法通过 动态维护多层级内存块 实现灵活管理,而非固定单一大小,但代价是内部碎片。这是其适合大内存管理但不适合小对象分配的根本原因。

2. Slab算法(Slab分配器)

2.1 核心思想

  • 频繁分配的小对象 预先分配缓存(Slab),避免反复调用 malloc/free
  • 适合管理 内核对象(如进程描述符、文件对象)。

2.2工作原理

  1. Slab分层结构
    • Cache:同一类对象的集合(如 task_struct 缓存)。
    • Slab:一个内存页(或连续页),存储多个对象。
    • Object:实际分配的内存单元。
  2. 分配流程
    • 空闲对象链表 直接获取,无需复杂计算。
  3. 释放流程
    • 对象放回链表,标记为可复用。

2.3示例

Cache: task_struct (每个1KB)
Slab1: [obj1][obj2][obj3] (已分配)
Slab2: [obj4][free][free] (部分空闲)

优点

  • 零碎片:对象大小固定,无内部/外部碎片。
  • 高性能:省去重复初始化开销(对象复用)。
  • 缓存友好:同一Slab的对象通常位于同一缓存行。

缺点

  • 内存浪费:Slab可能未完全利用(如部分对象空闲)。
  • 不适合大内存:仅针对小对象优化。

2.4应用场景

  • Linux内核的 kmalloc 小内存分配。
  • 数据库、网络协议栈的高频小对象分配。

3. Buddy vs Slab 对比

特性Buddy算法Slab算法
目标管理物理页(大内存)管理小对象(高频分配)
碎片问题外部碎片少,内部碎片多无碎片
分配速度中等(需拆分/合并)极快(直接取空闲链表)
内存利用率较低(2^n 对齐浪费)较高(对象复用)
适用场景物理页分配、嵌入式系统内核对象、高频小内存分配

4. 实际应用(Linux内核)

4.1Buddy系统

  • 管理 物理内存页(4KB/8KB等),通过 alloc_pages() 分配。
  • 通过 /proc/buddyinfo 查看状态:
    cat /proc/buddyinfo
    

4.2Slab分配器

  • 管理 内核对象(如 inodedentry),通过 kmem_cache_create() 创建缓存。
  • 通过 /proc/slabinfo 查看状态:
    cat /proc/slabinfo
    

5. 其他内存管理算法

  • malloc/free(glibc):基于 ptmalloc,结合 Buddy 和 Slab 思想。
  • jemalloc/tcmalloc:改进的多线程内存分配器,减少锁竞争。

6. 总结

  • Buddy算法:适合 大块物理内存管理,通过拆分/合并减少外部碎片。
  • Slab算法:适合 高频小对象分配,通过缓存复用提升性能。
  • 现代系统:通常 组合使用(如Linux用Buddy管理页,Slab管理对象)。

理解这两种算法,有助于优化 系统级内存管理高性能应用开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司六米希

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值