1. 程序描述符
1.1. 程序描述符的表示和存放
程序描述符task_struct
完整地描述了程序的所有資訊,它由slab分配器 (小記憶體分配)分配產生,並存放在叫任務佇列(task list)的雙向迴圈連結串列中。
一文看懂slab分配器實現
https://zhuanlan.zhihu.com/p/523241576
夥伴系統和slab分配:
slab分配:內部碎片和外部碎片
外部碎片指的是還沒有被分配出去(不屬於任何程序)但由於太小而無法分配給申請記憶體空間的新程序的記憶體空閒區域。外部碎片是除了任何已分配區域或頁面外部的空閒儲存塊。這些儲存塊的總和可以滿足當前申請的長度要求,但是由於它們的地址不連續或其他原因,使得系統無法滿足當前申請。簡單示例如下圖:
https://pic4.zhimg.com/80/v2-a8c043998653d8c3fe2e463c7262403b_1440w.webp
如果某程序現在需要向作業系統申請地址連續的32K記憶體空間,注意是地址連續,實際上系統中當前共有10K+23K=33K空閒記憶體,但是這些空閒記憶體並不連續,所以不能滿足程序的請求。這就是所謂的外部碎片,造成外部碎片的原因主要是程序或者系統頻繁的申請和釋放不同大小的一組連續頁框。Linux作業系統中為了儘量避免外部碎片而採用了夥伴系統(Buddy System)演算法 (頁表)2的n次方空間 4k 8k 16k
內部碎片就是已經被分配出去(能明確指出屬於哪個程序)卻不能被利用的記憶體空間;內部碎片是處於區域內部或頁面內部的儲存塊,佔有這些區域或頁面的程序並不使用這個儲存塊,而在程序佔有這塊儲存塊時,系統無法利用它。直到程序釋放它,或程序結束時,系統才有可能利用這個儲存塊。簡單示例如下圖:
某程序向系統申請了3K記憶體空間,系統透過夥伴系統演算法可能分配給程序4K(一個標準頁面)記憶體空間,導致剩餘1K記憶體空間無法被系統利用,造成了浪費。這是由於程序請求記憶體大小與系統分配給它的記憶體大小不匹配造成的。由於夥伴演算法採用頁框(Page Frame)作為基本記憶體區,適合於大塊記憶體請求。在很多情況下,程序或者系統申請的記憶體都是4K(一個標準頁面)的,依然採用夥伴演算法必然會造成系統記憶體的極大浪費。為滿足程序或者系統對小片記憶體的請求,對記憶體管理粒度更小的SLAB分配器就產生了。(注:Linux中的SLAB演算法實際上是借鑑了Sun公司的Solaris作業系統中的SLAB模式)
kalloc valloc
https://blog.csdn.net/lukuen/article/details/6935068
https://blog.csdn.net/goodluckwhh/article/details/10026311
https://zhuanlan.zhihu.com/p/358891862
若仍然分配一頁記憶體,這將嚴重浪費記憶體。那麼該如何分配呢?slab 分配器專為小記憶體分配而生,由Sun公司的一個僱員Jeff Bonwick
在Solaris 2.4
中設計並實現。slab分配器分配記憶體以位元組為單位,基於夥伴分配器的大記憶體進一步細分成小記憶體分配。換句話說,slab 分配器仍然從 Buddy 分配器中申請記憶體,之後自己對申請來的記憶體細分管理。
除了提供小記憶體外,slab 分配器的第二個任務是維護常用物件的快取。對於核心中使用的許多結構,初始化物件所需的時間可等於或超過為其分配空間的成本。當建立一個新的slab 時,許多物件將被打包到其中並使用建構函式(如果有)進行初始化。釋放物件後,它會保持其初始化狀態,這樣可以快速分配物件。
舉例來說, 為管理與程序關聯的檔案系統資料, 核心必須經常生成struct fs_struct
的新例項. 此型別例項佔據的記憶體塊同樣需要經常回收(在程序結束時). 換句話說, 核心趨向於非常有規律地分配並釋放大小為sizeof(fs_struct)
的記憶體塊. slab分配器將釋放的記憶體塊儲存在一個內部列表中. 並不馬上返回給夥伴系統. 在請求為該類物件分配一個新例項時, 會使用最近釋放的記憶體塊。S這有兩個優點. 首先, 由於核心不必使用夥伴系統演算法, 處理時間會變短. 其次, 由於該記憶體塊仍然是”新”的,因此其仍然駐留在CPU硬體快取的機率較高.[3]
SLAB分配器的最後一項任務是提高CPU硬體快取的利用率。 如果將物件包裝到SLAB中後仍有剩餘空間,則將剩餘空間用於為SLAB著色。 SLAB著色是一種嘗試使不同SLAB中的物件使用CPU硬體快取中不同行的方案。 透過將物件放置在SLAB中的不同起始偏移處,物件可能會在CPU快取中使用不同的行,從而有助於確保來自同一SLAB快取的物件不太可能相互重新整理。 透過這種方案,原本被浪費掉的空間可以實現一項新功能。
透過命令sudo cat /proc/slabinfo
可檢視系統當前 slab 使用情況。以vm_area_struct
結構體為例,當前系統已分配了 13014 個vm_area_struct
快取,每個大小為 216 位元組,其中 active 的有 12392 個。