什么是內存碎片?
內部碎片的產生:因為所有的內存分配必須起始於可被 4、8 或 16 整除(視 處理器體系結構而定)的地址或者因為MMU的分頁機制的限制,決定內存分配算法僅能把預定大小的內存塊分配給客戶。假設當某個客戶請求一個 43 字節的內存塊時,因為沒有適合大小的內存,所以它可能會獲得 44字節、48字節等稍大一點的字節,因此由所需大小四舍五入而產生的多余空間就叫內部碎片。
外部碎片的產生: 頻繁的分配與回收物理頁面會導致大量的、連續且小的頁面塊夾雜在已分配的頁面中間,就會產生外部碎片。假 設有一塊一共有100個單位的連續空閑內存空間,范圍是0~99。如果你從中申請一塊內存,如10個單位,那么申請出來的內存塊就為0~9區間。這時候你 繼續申請一塊內存,比如說5個單位大,第二塊得到的內存塊就應該為10~14區間。如果你把第一塊內存塊釋放,然后再申請一塊大於10個單位的內存塊,比 如說20個單位。因為剛被釋放的內存塊不能滿足新的請求,所以只能從15開始分配出20個單位的內存塊。現在整個內存空間的狀態是0~9空閑,10~14 被占用,15~24被占用,25~99空閑。其中0~9就是一個內存碎片了。如果10~14一直被占用,而以后申請的空間都大於10個單位,那么0~9就 永遠用不上了,變成外部碎片。
簡單介紹程序內存分配方式:
內存分配方式主要有連續型分配方式和非連續型分配方式,顧名思義,連續型分配方式就是分配連續的空間,非連續型分配方式就是分配非連續的內存空間。
連續型分配內存方式:
-
單一連續分配:
最簡單的分配方式,采用覆蓋技術。優點是無外部碎片,缺點是只能用於單用戶、有內部碎片、存儲利用率低。
-
固定分區分配:
最簡單的多道程序存儲管理方式,它將用戶內存空間划分為若干個固定大小(可以相等,也可以不等,同為4的倍數或其他),每個分區只裝入一道作業。當有空閑分區的時候,就從作業隊列里選擇適當大小的作業裝入該分區。為便於內存分配,通常將分區按大小排隊,並為之建立一張分區說明表,其中各項包括每個分區的起始地址,大小及狀態(是否被分配)。
無外部碎片,但是無法實現多進程共享一個主存區。
-
動態分區分配:
不預先划分內存,在程序裝入內存時,根據進程的大小動態地建立分區,並使得分區的大小正好適合進程的需要,因此系統中分區的大小和數目是可變的。
動態分區分配內存方式剛開始是很好地,但是,之后會導致內存出現很多的小的內存塊,也就是外部碎片。外部碎片可以通過緊湊來解決,就是操作系統不時地對進程進行移動和整理。但是需要動態重定位寄存器的支持。
動態分區分配在當系統有很大的內存塊的時候,分配內存必須要有一個策略。
1)首次適應:地址遞增,順序查找,第一個能滿足的即分配給進程。
2)最佳適應:容量遞增,找到第一個能滿足要求的空閑分區。
3)最壞適應:容量遞減,找到第一個能滿足要求的分區。
4)鄰近適應:循環首次適應算法。
當一個進程發生缺頁中斷的時候,進程會陷入內核態,執行以下操作:
1、檢查要訪問的虛擬地址是否合法
2、查找/分配一個物理頁
3、填充物理頁內容(讀取磁盤,或者直接置0,或者啥也不干)
4、建立映射關系(虛擬地址到物理地址)
重新執行發生缺頁中斷的那條指令
如果第3步,需要讀取磁盤,那么這次缺頁中斷就是majflt,否則就是minflt。
內存分配的原理
從操作系統角度來看,進程分配內存有兩種方式,分別由兩個系統調用完成:brk和mmap(不考慮共享內存)。
1、brk是將數據段(.data)的最高地址指針_edata往高地址推;
2、mmap是在進程的虛擬地址空間中(堆和棧中間,稱為文件映射區域的地方)找一塊空閑的虛擬內存。
這兩種方式分配的都是虛擬內存,沒有分配物理內存。在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,操作系統負責分配物理內存,然后建立虛擬內存和物理內存之間的映射關系。
在標准C庫中,提供了malloc/free函數分配釋放內存,這兩個函數底層是由brk,mmap,munmap這些系統調用實現的。
下面以一個例子來說明內存分配的原理:
情況一、malloc小於128k的內存,使用brk分配內存,將_edata往高地址推(只分配虛擬空間,不對應物理內存(因此沒有初始化),第一次讀/寫數據時,引起內核缺頁中斷,內核才分配對應的物理內存,然后虛擬地址空間建立映射關系),如下圖:
2、進程調用A=malloc(30K)以后,內存空間如圖2:
3、進程調用B=malloc(40K)以后,內存空間如圖3。
情況二、malloc大於128k的內存,使用mmap分配內存,在堆和棧之間找一塊空閑內存分配(對應獨立內存,而且初始化為0),如下圖:
5、進程調用D=malloc(100K)以后,內存空間如圖5;
6、進程調用free(C)以后,C對應的虛擬內存和物理內存一起釋放。
8、進程調用free(D)以后,如圖8所示: