先上基礎(chǔ),下圖是Linux的內(nèi)存映射模型
每一個進程都有自己的進程空間,進程空間的0-3G是用戶空間,3G-4G是內(nèi)核空間
每個進程的用戶空間不在同一個物理內(nèi)存頁,但是所有的進程的內(nèi)核空間對應(yīng)同樣的物理地址
vmalloc分配的地址可以高端內(nèi)存,也可以是低端內(nèi)存
0-896MB的物理地址是線性映射到物理映射區(qū)的。
內(nèi)核參數(shù)和系統(tǒng)頁表都在TEXT_OFFSET保存,除了進程除了訪問自身的用戶空間對應(yīng)的DRAM內(nèi)存頁外,都要經(jīng)過內(nèi)核空間,也就是都要切換到內(nèi)核態(tài)
內(nèi)存動態(tài)申請
和應(yīng)用層一樣,內(nèi)核程序也需要動態(tài)的分配內(nèi)存,不同的是,內(nèi)核進程可以控制分配的內(nèi)存是在用戶空間還是內(nèi)核空間,前者可以用于給用戶空間的堆區(qū)分配內(nèi)存,eg,用戶進程的用戶空間的malloc最終就會通過系統(tǒng)調(diào)用回調(diào)內(nèi)核空間的內(nèi)存分配函數(shù),此時該內(nèi)存分配函數(shù)就屬于該用戶進程,可以給在該用戶進程的堆區(qū)分配空間并返回,最終使得一個用會進程在自己的用戶空間獲得內(nèi)存分配;后者只在內(nèi)核空間分配,所以用戶進程不能直接訪問該空間,所以多用在滿足內(nèi)核程序自身的內(nèi)存需求,下面是Linux內(nèi)核空間申請內(nèi)存常用API:
kmalloc - kfree
kmalloc申請的內(nèi)存在物理內(nèi)存上是連續(xù)的,他們與真實的物理地址只有一個固定的偏移,因此存在簡單的轉(zhuǎn)換關(guān)系。這個API 多用來申請不到一個page大小的內(nèi)存。kmalloc的底層需要調(diào)用__get_free_pages,參數(shù)中表示內(nèi)存類型的gtp_t flags正是這個函數(shù)的縮寫,常用的內(nèi)存類型有GFP_USER,GFP_KERNEL,GFP_ATOMIC幾種。