核心把物理頁作為記憶體管理的基本單位。
32位系統:4k / 頁
64位系統:8k / 頁
由於硬體限制,核心不能對所有頁一視同仁。linux必須處理如下硬體存在的缺陷而引起的記憶體定址問題:
linux主要使用了四種區:
zone_dma —— 這個區包含的頁只能用來執行dma操作
zone_dma32 —— 和zone_dma類似,但只能被32位裝置訪問
zone_normal —— 這個區包含的頁都是能正常對映的頁
zone_highem —— 這個區包含「高階記憶體」,不能永久對映到核心位址空間
x86-32上的頁區
描述物理記憶體
zone_dma
dma使用的頁
< 16m
zone_normal
正常定址的頁
16m ~ 896m
zone_highem
動態對映的頁
> 896m
低階頁分配方法函式
描述struct page * allock_page(gfp_mask)
只分配一頁,返回指向頁結構的指標
struct page * allock_page(gfp_mask, order)
分配2的order次方個頁,返回指向第乙個頁結構的指標
unsigned long __get_free_page(gfp_mask)
只分配一頁,返回指向企邏輯位址的指標
unsigned long __get_free_pages(gfp_mask, order)
分配2的order次方個頁,返回指向第一頁邏輯位址的指標
unsigned long get_zoned_page(gfp_mask)
只分配一頁,讓其內容填充0,返回指向企邏輯位址的指標
頁釋放函式函式原型
描述void __free_pages(struct page * page, unsigned int order)
釋放page頁位址開始的2的order次方個頁
void free_pages(unsigned long addr, unsigned int order)
釋放addr位址開始的2的order次方個頁
void free_page(unsigned long addr)
釋放addr位址開始的乙個頁
struct page * allock_pages(gfp_t gfp_mask, unsigned int order)
該函式分配2的order次方個連續的物理頁,並返回指向第乙個頁的page結構體指標;如果出錯返回null。
void * page_address(struct page * page)
e.g.獲得8個頁,然後釋放:
unsigned long page;
page = __get_free_pages(gfp_kernel, 3); //申請8個頁
if (!page)
return -enomem; //沒有足夠記憶體free_pages(page, 3); //釋放
gfp_kernel是gfp_mask標誌的一種,後邊有說明
按位元組分配及釋放記憶體函式函式原型
描述void * kmalloc(size_t, gfp_t flags)
按照flags標誌分配至少size位元組大小的記憶體,且物理連續,返回指向記憶體塊的指標
void * vmalloc(unsigned long size)
按照flags標誌分配至少size位元組大小的記憶體,虛擬位址連續,實體地址不一定連續,返回指向記憶體塊的指標
void kfree(const void *ptr)
釋放由kmalloc申請的記憶體空間
void vfree(const void *addr)
釋放由vmalloc申請的記憶體空間
kmalloc 和 vmalloc的區別在於:
kmalloc()分配的是實體地址連續的記憶體(邏輯位址自然也是連續的),該函式是否允許休眠通過其引數flags來決定。
vmalloc()函式只確保頁在虛擬位址空間內是連續的,它通過分配非連續的物理記憶體塊,再「修正」頁表,把記憶體對映到邏輯位址空間的連續區域。
因此,該函式可能睡眠,不能在中斷上下文進行呼叫,也不能從其他不允許組賽的情況下呼叫。
出於效能考慮,核心**多用kmalloc()來獲得記憶體。
不管是在低階頁分配函式中,還是在kmalloc()中,都用到了分配器標誌。這些標誌可分為三類:行為修飾符、區段修飾符及型別。
行為修飾符表示你核心該如何分配所需記憶體,如:中斷處理程式需要核心分配記憶體過程中不能睡眠。
常用的行為修飾符標誌
描述__gfp_wait
分配器可以睡眠
__gfp_io
分配器可以啟動磁碟io
__gfp_fs
分配器可以啟動檔案系統io
__gfp_high
分配器可以訪問緊急事件緩衝池
區修飾符表示從哪個區中進行分配,zone_dma、zone_normal還是zone_highem。
區修飾符標誌
描述__gfp_dma32
從zone_dma分配
__gfp_dma32
只在zone_dma32分配
__gfp_highmem
從zone_highmem或zone_normal分配
型別標誌是行為修飾符和區修飾符的組合,如:gfp_kernel = (__gfp_wait | __gfp_io | __gfp_fs)
常用的型別標誌標誌
描述gfp_atomic
這個標誌用在中斷處理程式、下半部、持有自旋鎖以及其他不能睡眠的地方
gfp_kernel
這是一種常規分配方式,可能會阻塞。這個標誌在睡眠安全時用在程序上下文**中,
為了獲得呼叫者所需的記憶體,核心會盡力而為。這個標誌應當是首選標誌
請參考:
linux 核心學習 1 記憶體管理
1 分頁機制 早期計算機直接使用實體地址進行記憶體的使用和管理,但是硬體資源有限,而且不同的程式需要使用不同的實體地址,這樣給程式的管理和執行造成了很大的難度,而且極易造成乙個程式覆蓋其他程式的問題,使正常執行的程式出現錯誤。針對以上問題提出了使用虛擬位址與物理位址對映的管理方式,這樣每個程式都可以...
Linux 核心學習 4 記憶體管理
注 以下 有的是linux 5.10,有的是linux 2.6.30.4 1 arch x86 boot memory.c static void detect memory e820 void desc buf count while ireg.ebx count array size boot ...
linux核心學習筆記之記憶體管理
linux核心把物理頁作為記憶體管理的基本單位。每一頁的大小根據系統架構不同有所區別,32位系統下為4kb,64位系統下為8kb。記憶體管理單元 mmu 以頁為單位來管理系統中的頁表,負責虛擬位址到實體地址的轉換,使用者所使用的記憶體位址一般都是虛擬位址。核心中頁的結構體中比較重要的成員為 stru...