一篇文章搞懂Linux內存管理

一、兩種內存分配方式

  • 固定分區分配:將內存分成不同大小的分區,按照大小保存在一張分區表中,分區表中包括每個分區的起始地址、大小、以及狀態(是否分配),當有程序要裝入時,由內存分配程序依據用戶程序的大小檢索該表,從中找出一個能滿足要求的尚未分配的分區,並將分區狀態改爲已分配。
  • 動態分區分配:利用某種分配算法(下面會依次介紹每種分配算法),從空閒分區表中找到所需大小的分區。比如請求的分區大小爲size1,表中每個空閒分區的大小表示爲size2,假如size2-size1<=size(size是系統規定的不可再切割的剩餘分區大小),則不再切割,否則切割出所需大小,將剩餘部分扔留在空閒分區表中;當回收時,假如回收分區前後有空閒分區相鄰,則與最前面的空閒分區合併,只需改變最前面分區的大小,否則爲回收的分區單獨新建一個分區。

二、基於順序搜索的動態分區分配算法

適合中小型系統,大型系統的內存分區會很多,順序搜索的分區鏈比較長,所以搜索可用分區時會很慢。

1、首次適應算法

       該算法優先利用低內存中低地址部分的空閒分區,從而保留了高地址部分的大空閒區。這爲以後到達的大作業分配大的內存空間創造了條件。缺點是低地址部分不斷被劃分,會留下許多難以利用的內存碎片,而每次查找都是從低地址開始,所以越到後期查找可用分區開銷越大。

缺點:每次從最小分區開始,查找慢;先劃分最小分區,內存碎片多

優點:和下面相比,無

2、循環首次適應算法

      爲了解決首次適應算法的2個缺點,循環首次適應算法在爲進程分配內存空間時,不再是每次都從鏈首開始查找,而是從上找到的空閒分區的下一個空閒分區開始查找,直至找到一個能滿足要求的空閒分區,從中劃出一塊與請求大小相等的內存空間分配給作業。該算法能使內存中的空閒分區分佈得更均勻,從而減少了查找空閒分區時的開銷。

缺點:由於從中間開始分割,所以會缺乏大的空閒分區

優點:查找快

3、最佳適應算法

      將所有的空閒分區按容量從小到大的順序形成一個空閒分區鏈,每次分配內存時,總是把能滿足要求的最小空閒分區分配給作業,所以第一次找到的能滿足要求的空閒分區必然是最佳的。

缺點:每次分配後所切割下來的剩餘部分總是最小的,會造成大量內存碎片

優點:查找快

4、最壞適應算法

      空閒分區從大到小成鏈,每次分配內存時,總是挑選一個最大的空閒區,從中分割一部分存儲空間給作業使用,所以導致存儲器中缺乏大的空閒分區,所以成爲最壞適應算法。不過優點是可以使剩餘的空閒區不至於太小,產生碎片的可能性最小,同時它的查找效率很高。

缺點:缺乏大的空閒分區

優點:碎片少,查找效率高

三、基於索引搜索的動態分區分配算法

1、快速適應算法

      對於每一類具有相同容量的所有空閒分區,單獨設立一個空閒分區鏈表,同時設立一張管理索引表,每個索引項對應一種空閒分區大小,並記錄了該類型空閒分區鏈表投的指針。分配內存時不會切割,會直接分配能容納所需內存的最小分區。比如內存中分區有2k、4k、8k、16k,當前作業需要7k的內存大小,則分配8k的分區給它,並且不會進行分割

缺點:由於不進行切割,所以會有一定的內存浪費

優點:沒有內存碎片、查找效率高

2、夥伴系統算法

      無論已分配區或空閒分區,大小均爲2的k次冪,則系統剛開始運行時,整個內存區是一個大小爲2的n次方的空閒分區。在系統運行過程中,由於不斷劃分,將會形成若干個不連續的空閒分區,將這些分區按照分區的大小進行分類,對於具有相同大小的空閒分區,單獨設立一個空閒分區雙向鏈表,不同大小的空閒分區形成了多個空閒分區鏈表。

      當我們要分配大小爲n的內存時,會首先計算一個i值,2的i-1次方小於等於n,n小於等於2的i次方,若找到,則把該空閒分區分配給進程,否則在分區大小爲2的i+1次方的空閒分區鏈表中查找,將其分成兩個大小爲2的i次方的分區,一個分配給進程,剩下的一半放到n的i次方的分區鏈表中(如果2的i+1次方還沒有,則繼續依次向上查找)。回收時會執行和分配時相反的過程,同樣依次合併。

缺點:分割和合並花費時間較多

優點:使用索引搜索,速度有一定提升;空閒分區合併提高了空閒分區的使用率

3、哈希算法

      在分類搜索和夥伴系統中,都需要在一張管理索引表中查找到所需分區大小對應的鏈表頭指針,如果分區特別細的話,管理索引表會很長,查找開銷會變高。哈希則是爲管理索引表建立以分區大小爲關鍵字的哈希表,每一項記錄對應的空閒分區鏈表頭指針,分配時可以快速得到分區鏈表。

四、動態可重定位分配

優點:引入邏輯地址,有效降低內存碎片

      在前面介紹的分配算法中,或多或少都會產生很多太小的分區,不能被任何進程利用的內存碎片。所以引入邏輯地址,邏輯地址也叫相對地址,它存儲的是物理地址的偏移量。將相對地址轉換爲物理地址的操作被推遲到程序指令真正執行時,爲了使地址的轉換不影響程序的執行速度,在系統中增設了重定位寄存器,用來存放程序和數據在內存中的起始地址。在執行時,真正訪問的內存地址是相對地址與重定位寄存器中的地址相加形成的。

五、段頁式存儲管理方式

1、頁和塊的概念

      頁是指的邏輯地址(相對地址),塊是指的物理地址。分頁存儲管理將進程的邏輯地址空間分成若干個頁,併爲各頁從0開始編號,把物理內存地址空間分成若干個塊,也從0開始編號。在爲進程分配內存時,以塊爲單位將內存中的若干個頁分別裝入到多個可以不相鄰的物理塊中。

2、頁表

      在分頁系統中,允許將進程的各個頁離散地存儲在物理內存的任何一個物理塊中,爲了保證進程仍然能夠正確地運行,即能將每個頁中的邏輯地址轉換個塊的物理地址,系統又爲每個進程建立了一張頁面映像表,簡稱頁表。

      由於頁表也是存儲在內存中的,這使CPU每存取一個數據時,都要兩次訪問內存,第一次訪問內存中的頁表,第二次通過頁表中記錄的物理塊訪問真正的物理內存。      

     爲了提高地址變換速度,系統中增加了一個特殊的高速緩衝寄存器,取名爲TLB(Translation Look aside Buffer),用來存放當前訪問的那些頁表項(你可以理解成頁表的緩存)。所以每次訪問時可以從TLB中一次讀取出該頁對應的物理塊號,CPU減少了一次內存訪問,這也是爲什麼進程切換比線程切換開銷大的主要原因。

3、段頁

      在上面介紹的動態分區方式,都是爲整個進程分配一個連續的內存空間,引入分段式存儲管理系統後,則爲每個分段分配一個連續的分區(代碼段、數據段、全局區、堆、棧)。段表中存儲了所有的分段長度和對應頁的首地址,每個段的頁地址是邏輯連續的。

優點:

  • 是進程中的各個段可以離散地裝入內存中不同的分區中,不再是必須分配一個連續的內存分區
  • 對於開發人員來說,可以分別編寫和編譯,可以針對不同類型的段採取不同的保護,比如堆動態申請和釋放,棧自動申請和釋放
  • 允許若干個進程共享一個或多個分段

 

一枚正在努力的後端程序猿,碼字不易,看完了如果對您有幫助,動動小手點個贊評論一下,如果能給個關注再好不過啦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章