計算機操作系統(十七)內存管理
- 前言
- 一、內存的使用與程序重定位
- (一)內存是什么?
- (二)程序的重定位過程
- (三)總結:內存使用的核心問題
- 二、連續分區管理:早期的內存管理方案
- (一)什么是連續分區?
- (二)三種典型方案
- (三)連續分區的致命缺陷:內存碎片
- 三、分頁管理:用"拆分成小塊"解決碎片問題
- (一)核心思想:把內存和程序都切成小塊
- (二)分頁的優點
- (三)分頁的問題
- 四、分段管理:從"邏輯模塊"角度管理內存
- (一)為什么需要分段?
- (二)分段的核心概念
- (三)分段的優點
- (四)分段的缺點
- 五、段頁式管理:集大成者
- (一)設計思想:分段+分頁,取長補短
- (二)地址轉換過程(稍微復雜,但更靈活)
- (三)優缺點
- (四)實際應用
前言
- 在上一篇博客中,我們深入探討了進程同步,了解了進程間如何協調以避免沖突、有序執行。
- 進程運行離不開內存資源,因此,這一篇博客,我們將開啟內存管理的學習之旅,探究操作系統是如何高效管理內存,為進程運行保駕護航的。
我的個人主頁,歡迎來閱讀我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的操作系統博客專欄
https://blog.csdn.net/2402_83322742/category_12916780.html?spm=1001.2014.3001.5482
一、內存的使用與程序重定位
(一)內存是什么?
內存是計算機中用于臨時存儲數據和程序的硬件設備,就像我們日常辦公時的"書桌"。當我們要運行一個程序(比如打開瀏覽器),計算機需要先把程序從硬盤(相當于"文件柜")復制到內存這個"書桌"上,CPU才能快速讀取并執行。
(二)程序的重定位過程
-
程序的三種地址形態
- 邏輯地址:程序員寫代碼時用的"虛擬地址",比如在C語言中定義
int a=10;
,編譯器會給變量a
分配一個邏輯地址(例如0x1000),這個地址不考慮實際內存位置。 - 相對地址:經過匯編或編譯后生成的"相對起始地址"。比如一個程序模塊的相對地址從0開始,內部函數調用使用相對地址(如調用偏移量100的函數)。
- 物理地址:內存中真實的硬件地址,就像每個內存單元的"門牌號"(例如0x80000010)。
- 邏輯地址:程序員寫代碼時用的"虛擬地址",比如在C語言中定義
-
為什么需要重定位?
當程序被裝入內存時,它在內存中的起始位置是不確定的。比如同一個程序第一次從內存地址0x1000開始存放,第二次可能從0x5000開始。這時候程序內部的邏輯地址必須轉換成對應的物理地址,否則CPU會找不到正確的數據,就像快遞地址寫錯會導致包裹送錯地方。 -
兩種重定位方式
- 靜態重定位:在程序裝入內存時一次性完成地址轉換。就像搬家前把所有家具的位置在圖紙上標好,搬家時直接按圖紙擺放,之后不再改變。優點是簡單,缺點是程序一旦裝入就不能移動位置。
- 動態重定位:程序運行時通過硬件地址轉換機構(如基址寄存器)實時轉換地址。就像隨身攜帶一個"地址翻譯器",走到哪里都能把邏輯地址翻譯成當前位置的物理地址。優點是程序可以在內存中移動(比如內存緊湊時),缺點是需要額外的硬件支持。
(三)總結:內存使用的核心問題
程序要在內存中運行,必須解決"地址轉換"的問題,而重定位就是連接邏輯世界(程序員視角)和物理世界(硬件視角)的橋梁。
二、連續分區管理:早期的內存管理方案
(一)什么是連續分區?
- 把內存劃分為若干個連續的區域,每個區域分配給一個程序使用,就像把一塊大蛋糕切成若干塊,每塊給一個人吃。
- 早期的操作系統(如DOS)常用這種方式。
(二)三種典型方案
-
單一連續分區(最簡單的方案)
- 內存分為兩部分:一部分給操作系統(比如Windows的內核),剩下的全部給一個應用程序。
- 缺點:一次只能運行一個程序(想想看,你不能同時打開微信和瀏覽器),內存利用率極低。
-
固定分區(稍微進步一點)
- 提前把內存劃分為大小固定的幾個分區(比如1MB、2MB、4MB),每個分區可以存放一個程序。
- 問題:如果程序大小超過分區大小,無法裝入;如果程序太小,分區剩余空間浪費(比如一個500KB的程序裝入1MB的分區,浪費500KB)。
-
動態分區(按需分配)
- 不再提前劃分分區,而是根據程序需要動態劃分。比如程序需要3MB內存,就從空閑內存中切出3MB的連續空間。
- 關鍵問題:如何高效分配和回收空間?
- 分配算法:
- 首次適應:從內存起始位置開始找,第一個足夠大的空閑塊就分配,簡單但可能留下小碎片。
- 最佳適應:找最接近程序大小的空閑塊,看似合理,卻容易產生大量微小碎片(比如把大空閑塊切成剛好夠用的小塊,剩下的小碎片難以利用)。
- 回收問題:當程序運行結束釋放內存時,如果相鄰的空閑塊,需要合并成一個大的空閑塊,否則會形成不連續的碎片。
- 分配算法:
(三)連續分區的致命缺陷:內存碎片
無論是固定分區還是動態分區,都會面臨"碎片問題"。比如內存中有多個小的空閑塊,但合起來不夠一個程序使用(就像錢包里有很多零錢,但湊不出一張整鈔)。為了解決這個問題,操作系統不得不定期進行"內存緊湊"(把正在運行的程序移動到連續的區域,合并空閑塊),但這會消耗大量CPU資源。
三、分頁管理:用"拆分成小塊"解決碎片問題
(一)核心思想:把內存和程序都切成小塊
-
頁與頁框
- 把程序邏輯地址空間劃分為大小相等的"頁"(Page,比如4KB大小)。
- 把物理內存劃分為同樣大小的"頁框"(Page Frame,也叫頁幀)。
- 程序的每個頁可以裝入任意一個頁框,不需要連續,就像把一本書拆分成若干章節(頁),每個章節可以放在不同的書架格子(頁框)里,只要知道每個章節放在哪個格子,就能快速找到。
-
頁表:記錄"頁"的位置
- 每個程序有一張"頁表",記錄邏輯頁號到物理頁框號的映射關系。比如邏輯頁0對應物理頁框5,邏輯頁1對應物理頁框3。
- 地址轉換過程:當程序訪問邏輯地址(由頁號+頁內偏移組成),CPU通過頁表找到對應的頁框號,再加上頁內偏移,得到物理地址。例如:頁大小4KB(12位),邏輯地址0x1234(二進制0001 0010 0011 0100),前4位(0001)是頁號,后12位(0010 0011 0100)是頁內偏移。通過頁表查到頁號1對應的頁框號是3(二進制0011),物理地址就是0011 0010 0011 0100(0x3234)。
(二)分頁的優點
- 幾乎消除外部碎片:程序的頁可以分散存儲,只要有足夠的頁框就能裝入,不會因為空閑塊不連續而無法分配。
- 內存利用率高:頁的大小固定(通常4KB-8KB),每個程序最后一個頁即使沒裝滿,浪費的空間也很小(最多一個頁的大小),這叫"內部碎片",比連續分區的碎片問題好很多。
(三)分頁的問題
- 頁表占用內存:每個程序都需要頁表,如果頁表很大(比如64位系統),可能需要多級頁表(比如二級頁表、三級頁表)來減少內存占用。
- 程序員無感知:分頁是操作系統底層的機制,程序員不需要關心,所有地址轉換由硬件和操作系統自動完成。
四、分段管理:從"邏輯模塊"角度管理內存
(一)為什么需要分段?
分頁解決了內存碎片問題,但它是從"物理內存劃分"的角度設計的,而程序員寫程序時更習慣按邏輯模塊劃分(比如代碼段、數據段、堆棧段)。比如一個C程序包含main函數(代碼段)、全局變量(數據段)、函數調用棧(堆棧段),分段管理就是把這些邏輯模塊分別裝入內存,每個段可以獨立增長和共享。
(二)分段的核心概念
- 段:每個程序由若干個段組成,每個段有自己的名稱(如代碼段
.text
、數據段.data
)和長度。比如代碼段可能有10KB,數據段可能有5KB。 - 段表:記錄每個段的起始物理地址和長度。當程序訪問邏輯地址(段號+段內偏移),首先檢查段內偏移是否超過段長度(防止越界訪問,比如數組下標越界),然后用段號找到段的起始地址,加上偏移得到物理地址。
(三)分段的優點
- 符合程序邏輯結構:程序員可以直觀地理解內存布局,比如調試時知道代碼段在哪個區域,數據段在哪個區域。
- 支持段的共享與保護:多個程序可以共享同一個代碼段(比如共享C語言標準庫),每個段可以設置訪問權限(代碼段只讀,數據段可讀寫)。
(四)分段的缺點
- 外部碎片問題回歸:每個段需要連續的內存空間,段與段之間可能產生碎片(類似動態分區管理的問題)。
- 段大小不固定:大段可能難以分配,小段可能浪費空間(但比連續分區好,因為程序可以分成多個小段)。
五、段頁式管理:集大成者
(一)設計思想:分段+分頁,取長補短
- 先分段,再分頁:每個段被劃分為若干個頁,結合分段的邏輯模塊化和分頁的內存高效利用。
- 比如代碼段分成3個頁,數據段分成2個頁,每個頁裝入頁框,不需要連續。
- 地址結構:段號+段內頁號+頁內偏移。通過段表找到段對應的頁目錄表,再通過頁表找到頁框號,最后得到物理地址。
(二)地址轉換過程(稍微復雜,但更靈活)
- 程序訪問邏輯地址(段號S,段內邏輯地址A)。
- 通過段表找到該段的頁目錄表起始地址。
- 段內邏輯地址A分為頁號P和頁內偏移D。
- 通過頁目錄表和頁表找到頁框號F。
- 物理地址 = F×頁大小 + D。
(三)優缺點
- 優點:
- 既有分段的邏輯清晰(支持模塊劃分、共享、保護),又有分頁的內存高效(消除外部碎片,內部碎片少)。
- 適合大型程序和多任務系統(如Windows、Linux)。
- 缺點:
- 地址轉換需要多次訪問內存(段表+頁表),為了加速,通常使用"快表"(TLB,高速緩存)來緩存最近訪問的段頁信息。
- 管理復雜度最高,需要維護段表和頁表兩級結構。
(四)實際應用
現代操作系統(如x86架構的Linux、Windows)普遍采用段頁式管理,但為了簡化,有時會讓段的作用弱化(比如默認段號為0,只使用分頁),但底層機制仍支持分段與分頁的結合。
以上就是對本次關于操作系統博客內容的總結,后續我們將深入探討操作系統更多知識。
我的個人主頁,歡迎來閱讀我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的操作系統博客專欄
https://blog.csdn.net/2402_83322742/category_12916780.html?spm=1001.2014.3001.5482
非常感謝您的閱讀,喜歡的話記得三連哦 |