文章目錄

  • 前言
  • 摘要
  • 一、從內存分配失敗説起
  • 二、內存分區管理核心原理
  • 2.1 連續分配 vs 非連續分配
  • 2.2 內部碎片 vs 外部碎片
  • 三、固定分區分配
  • 3.1 固定分區原理
  • 四、動態分區分配
  • 4.1 動態分區原理
  • 4.2 動態分區分配算法
  • 4.3 詳細分配示例
  • 五、緊湊與夥伴系統
  • 5.1 緊湊技術
  • 5.2 夥伴系統
  • 六、內存分區管理總結
  • 6.1 核心要點
  • 6.2 考研408重點

前言

內存分區管理是操作系統內存管理的基礎。為什麼固定分區會產生內部碎片?動態分區為什麼會有外部碎片?首次適應、最佳適應、最壞適應有什麼區別?夥伴系統如何減少碎片? 理解連續分配策略、分區分配算法、碎片問題、緊湊技術,才能掌握內存管理的基礎原理。

摘要

從"內存碎片導致分配失敗"故障出發,剖析內存分區管理的核心原理。通過固定分區的內部碎片分析、動態分區的分配算法對比、外部碎片的緊湊解決、夥伴系統的折中策略,揭秘連續內存分配的完整機制。配合詳細計算推導,給出碎片率、分配效率的透徹理解。


一、從內存分配失敗説起

週三上午,哈吉米啓動程序失敗:

場景1:空閒內存夠但無法分配

系統狀態:
  物理內存:8GB
  已分配:6GB
  空閒:2GB
  
啓動程序:
  需要內存:1.5GB
  
結果:
  分配失敗!
  
查看內存:
  空閒塊1:500MB
  空閒塊2:600MB
  空閒塊3:400MB
  空閒塊4:500MB
  
總空閒:2GB > 1.5GB ✓
但沒有連續的1.5GB塊 ❌

哈吉米:“總空閒內存夠,為什麼分配不了?”

南北綠豆:“這是外部碎片——空閒內存分散,無法滿足大塊分配。”


場景2:固定分區的浪費

固定分區方案:
  分區1:1GB(分配給進程A,實際用500MB)
  分區2:1GB(分配給進程B,實際用800MB)
  分區3:1GB(分配給進程C,實際用900MB)
  分區4:1GB(空閒)
  
浪費空間:
  分區1浪費:500MB
  分區2浪費:200MB
  分區3浪費:100MB
  總浪費:800MB

哈吉米:“分配了1GB但只用了一部分,浪費了。”

阿西噶阿西:“這是內部碎片——分配的塊內有未使用空間。”


二、內存分區管理核心原理

2.1 連續分配 vs 非連續分配

南北綠豆:“內存分配分為連續和非連續兩大類。”

分配方式

説明

優點

缺點

連續分配

進程佔用連續內存

簡單、訪問快

碎片、不靈活

非連續分配

進程可佔用分散內存

無外部碎片、靈活

複雜、需要頁表

連續分配方式:
  - 固定分區
  - 動態分區
  - 夥伴系統
  
非連續分配方式:
  - 分頁(已講)
  - 分段
  - 段頁式

2.2 內部碎片 vs 外部碎片

碎片類型對比

類型

定義

產生原因

解決方法

內部碎片

分配塊內的未使用空間

分配單位大於需求

減小分配單位

外部碎片

分配塊之間的未使用空間

分配釋放導致分散

緊湊、非連續分配

圖示

內部碎片:
  |------ 分配的1GB ------|
  |已使用500MB|內部碎片500MB|
  
外部碎片:
  |進程A|外部碎片|進程B|外部碎片|進程C|
        ↑             ↑
     100MB         200MB
     分散,無法合併使用

生活化比喻

停車場場景:

內部碎片:
  車位(分配單位):5米
  汽車(實際需求):4米
  浪費:1米(內部碎片)
  
外部碎片:
  |車1|空1米|車2|空0.5米|車3|
     ↑        ↑
  分散的空位,停不進新車(外部碎片)

哈吉米:“內部碎片在塊內,外部碎片在塊間。”


三、固定分區分配

3.1 固定分區原理

原理:將內存劃分為若干固定大小的分區。

分區方案

方案1:分區大小相等
  |1MB|1MB|1MB|1MB|1MB|1MB|1MB|1MB|
  
  優點:簡單
  缺點:大進程裝不下,小進程浪費大
  
方案2:分區大小不等
  |512K|512K|1MB|1MB|2MB|2MB|4MB|
  
  優點:靈活
  缺點:仍有內部碎片

分配數據結構

分區表:

| 分區號 | 起始地址 | 大小 | 狀態 | 進程號 |
|--------|---------|------|------|--------|
| 1      | 0x0000  | 512K | 空閒 | -      |
| 2      | 0x0800  | 512K | 已分配| P1    |
| 3      | 0x1000  | 1MB  | 空閒 | -      |
| 4      | 0x2000  | 2MB  | 已分配| P2    |

分配流程圖

graph TB
    Start[進程請求內存] --> Size[檢查所需大小]
    
    Size --> Search[查找分區表]
    
    Search --> Find{找到合適空閒分區?}
    
    Find -->|是| Check{分區大小≥需求?}
    
    Check -->|是| Alloc[分配分區]
    Alloc --> Update[更新分區表]
    Update --> Success[分配成功]
    
    Check -->|否| Find
    
    Find -->|否| Fail[分配失敗]
    
    Success --> Frag[產生內部碎片]

內部碎片計算

例子:
  進程需求:700KB
  分配分區:1MB
  
內部碎片 = 1024KB - 700KB = 324KB
碎片率 = 324 / 1024 = 31.6%

南北綠豆:“固定分區簡單但浪費大,現代系統很少用。”


四、動態分區分配

4.1 動態分區原理

原理:根據進程需求動態劃分內存,分區大小可變。

分配示例

初始狀態:
  |--------- 8GB空閒 ---------|
  
分配進程P1(1GB):
  |-- P1(1GB) --|-- 7GB空閒 --|
  
分配進程P2(2GB):
  |P1(1GB)|-- P2(2GB) --|5GB空閒|
  
分配進程P3(1.5GB):
  |P1|P2|-- P3(1.5GB) --|3.5GB空閒|
  
釋放P2:
  |P1|-- 2GB空閒 --|P3|3.5GB空閒|
     ↑ 外部碎片產生

空閒分區鏈表

空閒分區表:

| 起始地址 | 大小 | 下一個 |
|---------|------|--------|
| 0x1000  | 2GB  | →      |
| 0x5000  | 3.5GB| NULL   |

4.2 動態分區分配算法

首次適應(First Fit)

原理:
  從頭開始查找,分配第一個足夠大的空閒塊
  
例子:
  空閒塊:[10MB, 5MB, 20MB, 15MB]
  需求:12MB
  
  掃描:
    10MB < 12MB ❌
    5MB < 12MB ❌
    20MB ≥ 12MB ✓ 分配這個
  
  結果:
    分配20MB中的12MB
    剩餘8MB加入空閒鏈表

最佳適應(Best Fit)

原理:
  查找最接近需求的空閒塊(浪費最小)
  
例子:
  空閒塊:[10MB, 5MB, 20MB, 15MB]
  需求:12MB
  
  掃描所有:
    10MB:差2MB ❌
    5MB:差7MB ❌
    20MB:差8MB
    15MB:差3MB ← 最接近 ✓
  
  結果:
    分配15MB中的12MB
    剩餘3MB(小碎片)

最壞適應(Worst Fit)

原理:
  分配最大的空閒塊(剩餘塊儘量大)
  
例子:
  空閒塊:[10MB, 5MB, 20MB, 15MB]
  需求:12MB
  
  找最大:
    20MB ← 最大 ✓
  
  結果:
    分配20MB中的12MB
    剩餘8MB(較大,可再利用)

三種算法對比

算法

策略

優點

缺點

適用

首次適應

第一個夠用的

快速

前端碎片多

通用⭐

最佳適應

最接近的

浪費小

產生小碎片,慢

內存緊張時

最壞適應

最大的

剩餘塊大

大塊很快用完

很少用

算法對比示意圖













首次適應FF

最佳適應BF

最壞適應WF

空閒塊1:10MB

空閒塊2:5MB

空閒塊3:20MB選中

空閒塊1:10MB

空閒塊2:5MB

空閒塊3:20MB

空閒塊4:15MB選中

空閒塊1:10MB

空閒塊2:5MB

空閒塊3:20MB選中

空閒塊4:15MB


哈吉米:“首次適應最快,最佳適應最省,最壞適應用得少。”


4.3 詳細分配示例

問題

初始空閒塊:[20KB, 10KB, 30KB, 15KB]
請求序列:
  1. 分配12KB
  2. 分配10KB
  3. 釋放12KB
  4. 分配15KB
  
分別用首次適應、最佳適應、最壞適應,畫出每步狀態

首次適應

操作

空閒塊狀態

説明

初始

[20, 10, 30, 15]

-

分配12KB

[8, 10, 30, 15]

從20KB分配(首個夠用)

分配10KB

[8, 0, 30, 15]

從10KB分配(剛好)

釋放12KB

[8, 0, 30, 15, 12]

12KB加入尾部

分配15KB

[8, 0, 15, 15, 12]

從30KB分配

最佳適應

操作

空閒塊狀態

説明

初始

[20, 10, 30, 15]

-

分配12KB

[20, 10, 30, 3]

從15KB分配(最接近)

分配10KB

[20, 0, 30, 3]

從10KB分配(剛好)

釋放12KB

[20, 0, 30, 3, 12]

12KB加入尾部

分配15KB

[5, 0, 30, 3, 12]

從20KB分配(最接近)

最壞適應

操作

空閒塊狀態

説明

初始

[20, 10, 30, 15]

-

分配12KB

[20, 10, 18, 15]

從30KB分配(最大)

分配10KB

[10, 10, 18, 15]

從20KB分配(最大)

釋放12KB

[10, 10, 18, 15, 12]

12KB加入尾部

分配15KB

[10, 10, 3, 15, 12]

從18KB分配(最大)

阿西噶阿西:“不同算法導致碎片分佈不同。”


五、緊湊與夥伴系統

5.1 緊湊技術

原理:移動進程,合併空閒碎片。

緊湊過程

緊湊前:
  |P1|碎片1|P2|碎片2|P3|碎片3|
  |2MB|1MB|3MB|2MB|1MB|3MB|
  
緊湊後:
  |P1|P2|P3|------ 空閒6MB ------|
  |2MB|3MB|1MB|

緊湊時序圖


操作系統 進程P1 進程P2 進程P3 暫停所有進程 保持位置不動 移動到P1後面 更新頁表/地址 移動到P2後面 更新頁表/地址 合併尾部空閒區 恢復所有進程 操作系統 進程P1 進程P2 進程P3


緊湊開銷

開銷

説明

時間

移動數據需要時間(GB級數據秒級)

暫停進程

緊湊期間進程暫停

更新地址

需要更新所有地址指針

緊湊時機:
  1. 空閒碎片過多時
  2. 無法分配大塊時
  3. 系統空閒時

南北綠豆:“緊湊解決外部碎片,但開銷大。”


5.2 夥伴系統

原理:折中方案,塊大小為2的冪,易於分裂與合併。

夥伴系統規則

塊大小:
  1KB, 2KB, 4KB, 8KB, 16KB, ..., 512KB, 1MB
  
分配規則:
  1. 向上取整到2的冪
  2. 從對應大小鏈表取塊
  3. 如果沒有,從更大塊分裂
  
釋放規則:
  1. 釋放塊加入鏈表
  2. 檢查夥伴是否空閒
  3. 如果夥伴空閒,合併成大塊

夥伴計算

夥伴判斷:
  兩個塊大小相同
  地址相鄰
  起始地址滿足:addr % (2 × size) == 0
  
例子:
  塊A:起始0x0000,大小64KB
  塊B:起始0x10000,大小64KB
  
  檢查:
    大小相同 ✓
    相鄰 ✓
    0x0000 % 128KB = 0 ✓
    → A和B是夥伴

夥伴系統示例

初始:1MB空閒

請求70KB:
  向上取整:128KB
  
  分裂過程:
    1MB → 512KB + 512KB(分裂)
    512KB → 256KB + 256KB(分裂)
    256KB → 128KB + 128KB(分裂)
    分配:128KB
  
  結果:
    已分配:128KB(給進程)
    空閒:128KB, 256KB, 512KB

夥伴系統結構圖


作業內存內存管理之固定分區和動態分區詳解_51CTO博客_#java


分配與釋放過程

操作

過程

結果

分配70KB

向上→128KB,從256KB分裂

分配128KB,剩餘128KB

分配35KB

向上→64KB,從128KB分裂

分配64KB,剩餘64KB

釋放70KB

釋放128KB,與夥伴合併

合併為256KB

夥伴系統優缺點

優點:
  ✓ 分配快(鏈表查找)
  ✓ 易於合併(夥伴檢查)
  ✓ 碎片較少
  
缺點:
  ✗ 有內部碎片(向上取整)
  ✗ 某些大小浪費大(如65KB→128KB)

哈吉米:“夥伴系統是固定和動態的折中。”


六、內存分區管理總結

6.1 核心要點

南北綠豆總結:

  1. 連續分配:進程佔用連續內存,簡單但有碎片
  2. 固定分區:塊大小固定,有內部碎片
  3. 動態分區:塊大小可變,有外部碎片
  4. 分配算法:首次適應(快)、最佳適應(省)、最壞適應(少用)
  5. 緊湊:移動進程合併碎片,開銷大
  6. 夥伴系統:折中方案,塊大小為2的冪

6.2 考研408重點

阿西噶阿西

作業內存內存管理之固定分區和動態分區詳解_51CTO博客_內部碎片_02

必考題型:
  ✓ 內部碎片vs外部碎片
  ✓ 首次適應、最佳適應、最壞適應模擬
  ✓ 碎片率計算
  ✓ 夥伴系統分配過程
  ✓ 緊湊前後內存佈局

必記公式:
  ✓ 內部碎片 = 分配大小 - 實際需求
  ✓ 碎片率 = 碎片大小 / 分配大小
  ✓ 夥伴系統:向上取整到2的冪

必記要點:
  ✓ 內部碎片:分配塊內浪費
  ✓ 外部碎片:分配塊間分散
  ✓ 首次適應:快速,前端碎片多
  ✓ 最佳適應:省空間,產生小碎片
  ✓ 最壞適應:剩餘塊大,很少用
  ✓ 緊湊:移動進程,合併碎片
  ✓ 夥伴系統:塊大小為2^n

計算技巧:
  ✓ 畫表格模擬分配過程
  ✓ 標註每個空閒塊的大小
  ✓ 首次適應:從頭掃描
  ✓ 最佳適應:掃描全部,選最小夠用
  ✓ 最壞適應:掃描全部,選最大
  ✓ 夥伴系統:向上取整到2^n

典型考題:
  題:空閒塊[20KB, 10KB, 30KB],請求序列12KB, 10KB, 15KB,
      用首次適應,畫出每步狀態
      
  答:
    初始:[20, 10, 30]
    分配12KB:[8, 10, 30](從20KB分配)
    分配10KB:[8, 0, 30](從10KB分配)
    分配15KB:[8, 0, 15](從30KB分配)

哈吉米:“掌握了內存分區管理,408內存管理基礎就完全理解了。”

作業內存內存管理之固定分區和動態分區詳解_51CTO博客_#服務器_03


參考資料

  • 《操作系統概念》(第9版)- Abraham Silberschatz
  • 《現代操作系統》(第4版)- Andrew S. Tanenbaum
  • 《計算機操作系統》(第4版)- 湯小丹
  • 408統考大綱 - 操作系統部分