印度官員:歡迎特斯拉印度建廠,不應從中國進口
Linux記憶體管理
1、頁
核心將物理頁作為記憶體管理的基本單位。從虛擬記憶體的角度看,頁是最小的單位。在不同的計算機體系結構中,頁的大小不盡相同。32位系統支援4KB的頁,而64位系統則會支援8KB的頁。
核心用struct page
結構來表示系統中的每個物理頁。其中包括了物理頁的引用計數、物理頁的狀態,如是否為髒頁,是否被鎖定等。其中virtual
表示頁的虛擬地址。通常情況下它就是頁在虛擬記憶體中的地址。page
結構與物理頁相關,而並非與虛擬頁相關。核心僅僅用這個結構來描述此刻在相關的物理頁中存放的東西。這種結構的目的在於描述實體記憶體本身而非其中的資料。
2、區
由於硬體的限制,核心將頁劃分為不同的區。核心使用區對具有相似性的頁進行分組。Linux必須處理如下兩種由於硬體存在缺陷而引起的記憶體定址問題。1)一些硬體只能用某些特定的記憶體地址來執行DMA
ZONE_DMA
:這個區包含的頁能用來執行DMA
操作。2)ZONE_DMA32
:和ZONE_DMA
不同之處在於,這些頁面能夠被32位裝置訪問。在某些體系機構中,該區將比ZONE_DMA
更大。3)ZONE_NORMAL
:這個區包含的都是能夠正常對映的頁。4)ZONE_HIGHMEM
:這個區包含“高階記憶體”,其中的頁並不能永久對映到核心地址空間。
核心對於頁不同區的劃分沒有任何物理意義,只是核心為了管理頁而採用的一種邏輯分組。某些分配可能需要從特定的區中獲得頁,而另外一些分配則可以從多個區中獲得頁,但不能同時從兩個區分配,因為分配是不能跨區界限的。不是所有的體系結構都定義了全部區,如x86-64
ZONE_HIGHMEM
區,所有實體記憶體都處於ZONE_DMA
和ZONE_NORMAL
。
3、slab層
在系統中為了便於資料的頻繁分配和回收多使用空閒連結串列,空閒連結串列包含可供使用的、已經分配好的資料結構塊。當代碼需要使用一個新的資料結構例項時,就可以從空閒連結串列中抓取一個,而不需要分配記憶體,再把資料放進去。當不再需要這個資料結構例項時,就將它放回到空閒連結串列,而不是釋放。在核心中,空閒連結串列一個主要問題是不能全域性控制。當可用記憶體變得緊缺時,核心無法通知每個空閒連結串列讓其收縮快取大小以便釋放一些記憶體。實際上,核心根本不知道存在任何空閒連結串列。
slab層將不同的物件劃分為所謂快取記憶體組,讓每個快取記憶體組都存放不同型別的物件。每種物件型別對應一個快取記憶體。之後,這些快取記憶體又被劃分為slab,slab由一個或者多個物理上連續的頁組成。每個快取記憶體可以由多個slab組成。每個slab都包含一些物件成員,處於三種狀態之一:滿、部分滿或者空。當核心的某一部分需要一個新的物件時,先從部分滿的slab進行分配,如果沒有部分滿的slab,就從空的slab中進行分配。如果沒有空的slab,就要建立一個slab。
slab層的管理是在每個快取記憶體的基礎上,通過提供給整個核心一個簡單的介面來完成的。通過介面就可以建立和撤銷新的快取記憶體,並在快取記憶體內分配和釋放物件。
4、分配函式的選擇
如果需要連續的物理頁,就可以使用某個低階頁分配器或者kmalloc()
。這是核心中記憶體分配的常用方式。傳遞的常用標誌是GFP_ATOMIC
和GFP_KERNEL
。分別表示進行不進行睡眠的高優先順序分配和可以睡眠的分配。
如果需要從高階記憶體進行分配,就使用alloc_pages()
,函式返回一個指向struct page
結構的指標,而不是一個指向某個邏輯地址的指標。因為高階記憶體可能並沒有被對映。為了獲得真正的指標,應該呼叫kmap()
,把高階記憶體對映到核心的邏輯地址空間。
如果不需要物理上連續的頁,僅需要虛擬地址上連續的頁,就使用vmalloc()
。函式分配的記憶體虛擬地址連續,但本身並不保證物理上的連續。
如果要建立和撤銷很多大的資料結構,考慮建立slab告訴快取。會極大提高物件分配和回收的效能。