0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux內(nèi)核內(nèi)存管理之內(nèi)核非連續(xù)物理內(nèi)存分配

jf_0tjVfeJz ? 來源:嵌入式ARM和Linux ? 2024-02-23 09:44 ? 次閱讀

1 非連續(xù)內(nèi)存區(qū)的線性地址

2 非連續(xù)內(nèi)存區(qū)的描述符

3 申請非連續(xù)物理內(nèi)存區(qū)

4 釋放非連續(xù)內(nèi)存區(qū)

5 vmalloc和kmalloc

我們已經(jīng)知道,最好將虛擬地址映射到連續(xù)頁幀,從而更好地利用緩存并實現(xiàn)更低的平均內(nèi)存訪問時間。然而,如果對內(nèi)存區(qū)域的請求并不頻繁,那么考慮基于通過連續(xù)線性地址訪問非連續(xù)頁幀的分配方案是有意義的。該模式的主要優(yōu)點是避免了外部碎片,而缺點是需要修改內(nèi)核頁表。顯然,非連續(xù)內(nèi)存區(qū)域的大小必須是4096的倍數(shù)。Linux使用非連續(xù)物理內(nèi)存區(qū)的場景有幾種:(1)為swap區(qū)分配數(shù)據(jù)結(jié)構(gòu);(2)為模塊分配空間(參見附錄B);(3)或者為一些I/O驅(qū)動程序分配緩沖區(qū)。此外,非連續(xù)物理內(nèi)存區(qū)還提供了另一種利用高端內(nèi)存的方法。

1 非連續(xù)內(nèi)存區(qū)的線性地址

要查找線性地址的空閑范圍,我們可以從PAGE_OFFSET開始的區(qū)域(通常是0xc0000000,3G→4G)。下圖展示了這1G的線性地址的使用方式:

這1G大小的線性地址的第一部分是映射前896M物理內(nèi)存的線性地址;與直接映射的物理內(nèi)存的結(jié)尾對應(yīng)的線性地址存儲在high_memory變量中。

這1G大小的線性地址的最后部分是固定映射的線性地址。

從PKMAP_BASE線性地址開始,是高端內(nèi)存頁幀的永久內(nèi)核映射使用的線性地址空間。

余下的線性地址空間用作非連續(xù)內(nèi)存區(qū)域的映射。在前896M的線性地址之后與第一個非連續(xù)內(nèi)存空間插入一個安全樁(大小為8M的地址間隔,使用宏VMALLOC_OFFSET獲取該值),以便捕獲越界內(nèi)存訪問。基于這個目的,后面每個非連續(xù)內(nèi)存區(qū)域之間都插入一個4K大小的地址間隔。

c1082398-d172-11ee-a297-92fbcf53809c.png

圖8-8 內(nèi)核地址空間的布局

VMALLOC_START宏定義了為非連續(xù)內(nèi)存區(qū)保留的線性空間的起始地址,而VMALLOC_END定義了它的結(jié)束地址。

2 非連續(xù)內(nèi)存區(qū)的描述符

每個非連續(xù)內(nèi)存區(qū)都有一個類型為vm_struct的描述符進行表達,各個成員如下所示:

表8-13 vm_struct各個成員的描述

類型 名稱 描述
void * addr 該區(qū)域的第一個存儲單元的線性地址
unsigned long size 該區(qū)域的大小+4096(內(nèi)存區(qū)域間的安全間隔)
unsigned long flags 映射的內(nèi)存類型
struct page ** pages 指向頁描述符的nr_pages指針數(shù)組
unsigned int nr_pages 該區(qū)域填充的頁數(shù)
unsigned long phys_addr 設(shè)置為0,除非是創(chuàng)建的內(nèi)存區(qū)用來映射硬件設(shè)備的I/O共享內(nèi)存
struct vm_struct* next 指向下一個vm_struct結(jié)構(gòu)

這些描述符通過“next”字段插入到一個簡單的列表中;列表中第一個元素的地址存儲在vmlist變量中。通過“vmlist_lock”讀/寫自旋鎖保護對該列表的訪問。flags字段標識該內(nèi)存區(qū)映射的內(nèi)存類型:VM_ALLOC用于通過vmalloc()獲得的頁面,VM_MAP用于通過vmap()映射的已經(jīng)分配的頁面(參見下一節(jié)),VM_IOREMAP用于通過ioremap()映射的硬件設(shè)備的板載內(nèi)存(參見第13章)。

get_vm_area()負責在VMALLOC_START和VMALLOC_END之間找一段空閑的連續(xù)線性地址。這個函數(shù)作用于兩個參數(shù):size,要創(chuàng)建的內(nèi)存區(qū)的字節(jié)數(shù);flag,指定要創(chuàng)建的內(nèi)存類型。執(zhí)行以下步驟:

structvm_struct*__get_vm_area(unsignedlongsize,unsignedlongflags,
unsignedlongstart,unsignedlongend)
{
structvm_struct**p,*tmp,*area;
unsignedlongalign=1;
unsignedlongaddr;

//...省略
addr=ALIGN(start,align);

/*1.創(chuàng)建一個內(nèi)核slab通用對象,
*保存vm_struct(一段虛擬內(nèi)存的描述符)的內(nèi)容
*/
area=kmalloc(sizeof(*area),GFP_KERNEL);
if(unlikely(!area))
returnNULL;

/*
*2.創(chuàng)建一個保護頁(4K大小的間隔)
*/
size+=PAGE_SIZE;
if(unlikely(!size)){
kfree(area);
returnNULL;
}

/*3.獲取用于寫入的vmlist_lock鎖,
*并掃描類型為vm_struct的描述符列表(也就是vmlist),
*查找至少包含size+4096的線性地址空間
*(4k是內(nèi)存區(qū)域之間的安全間隔的大小)。
*/
write_lock(&vmlist_lock);
for(p=&vmlist;(tmp=*p)!=NULL;p=&tmp->next){
if((unsignedlong)tmp->addraddr+tmp->size>=addr)
addr=ALIGN(tmp->size+
(unsignedlong)tmp->addr,align);
continue;
}
if((size+addr)addr)
gotofound;
addr=ALIGN(tmp->size+(unsignedlong)tmp->addr,align);
if(addr>end-size)
gotoout;
}

found:
/*4.如果找到合適的一段線性地址空間,
*則初始化申請的描述符并釋放鎖,
*然后返回描述符的地址。
*/
area->next=*p;
*p=area;

area->flags=flags;
area->addr=(void*)addr;
area->size=size;
area->pages=NULL;
area->nr_pages=0;
area->phys_addr=0;
write_unlock(&vmlist_lock);

returnarea;

out:
/*5.釋放獲得的描述符,并釋放鎖,并返回NULL*/
write_unlock(&vmlist_lock);
kfree(area);
returnNULL;
}

3 申請非連續(xù)物理內(nèi)存區(qū)

vmalloc()函數(shù)為內(nèi)核分配了一個非連續(xù)物理內(nèi)存。參數(shù)size表示請求內(nèi)存的大小。如果函數(shù)能夠滿足請求,則返回新區(qū)域的初始線性地址;否則,它返回一個NULL指針:

void*vmalloc(unsignedlongsize)
{
structvm_struct*area;
structpage**pages;
unsignedintarray_size,i;

//將size按照4k對齊
size=(size+PAGE_SIZE-1)&PAGE_MASK;
//創(chuàng)建新的頁描述符并返回對應(yīng)的線性地址
//標志是VM_ALLOC,表示非連續(xù)物理頁幀將被映射到一段線性地址空間
area=get_vm_area(size,VM_ALLOC);
if(!area)
returnNULL;

area->nr_pages=size>>PAGE_SHIFT;
array_size=(area->nr_pages*sizeof(structpage*));
//申請一個數(shù)組的物理內(nèi)存對象,保存頁描述符指針數(shù)組
area->pages=pages=kmalloc(array_size,GFP_KERNEL);
if(!area_pages){
remove_vm_area(area->addr);
kfree(area);
returnNULL;
}
//將指針數(shù)組的元素清零。
memset(area->pages,0,array_size);
/*根據(jù)需要的內(nèi)存頁數(shù),重復調(diào)用alloc_page函數(shù)
*給每一個頁分配一個頁幀,并將相應(yīng)的頁描述符存入數(shù)組中。
*注意,這兒使用數(shù)據(jù)保存頁描述符是非常有必要的,
*因為這些頁幀屬于高端內(nèi)存,它們不用映射為線性地址。
*/
for(i=0;inr_pages;i++){
area->pages[i]=alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
if(!area->pages[i]){
area->nr_pages=i;
fail:vfree(area->addr);
returnNULL;
}
}
/*到這兒,我們已經(jīng)獲得了一段線性地址空間;
*也獲得了一組非連續(xù)的物理頁幀。那么關(guān)鍵的一步就是,
*修改頁表項,將每個分配的頁幀與一個線性地址建立映射關(guān)系
*實現(xiàn)的函數(shù)就是map_vm_area
*/
if(map_vm_area(area,__pgprot(0x63),&pages))
gotofail;
returnarea->addr;
}

將線性地址與非連續(xù)物理頁幀建立映射關(guān)系由map_vm_area()函數(shù)實現(xiàn),使用3個參數(shù):

area:指向該內(nèi)存區(qū)域的vm_struct描述符的指針。

prot:已分配頁幀的保護位??偸窃O(shè)為0x63,對應(yīng)于Present、Accessed、Read/Write和Dirty

pages: 指向頁描述符指針數(shù)組的變量的地址(因此,struct page ***用作數(shù)據(jù)類型?。?。

具體代碼如下所示:

intmap_vm_area(structvm_struct*area,pgprot_tprot,structpage***pages)
{
/*1.獲取線性地址的起始位置、結(jié)束位置*/
unsignedlongaddress=(unsignedlong)area->addr;
unsignedlongend=address+(area->size-PAGE_SIZE);
unsignedlongnext;
pgd_t*pgd;
interr=0;
inti;

/*2.使用pgd_offset_k宏在主內(nèi)核PGD頁全局目錄中
*導出與該區(qū)域的初始線性地址相關(guān)的表項
*/
pgd=pgd_offset_k(address);

/*3.申請內(nèi)核頁表自旋鎖*/
spin_lock(&init_mm.page_table_lock);
for(i=pgd_index(address);i<=?pgd_index(end-1);?i++)?{

????????/*?4.?為新內(nèi)存分配PUD頁表中間目錄,
?????????*????并將其正確的物理地址寫入PGD目錄中
?????????*/
????????pud_t?*pud?=?pud_alloc(&init_mm,?pgd,?address);
????????if?(!pud)?{
????????????err?=?-ENOMEM;
????????????break;
????????}

????????/*?5.?分配與新PUD目錄關(guān)聯(lián)的所有頁表。
?????????*????map_area_pud將單個PUD所跨越的線性地址范圍的大小
?????????*????(如果啟用了PAE,則為常數(shù)2^30,否則為2^22)加到當前的
?????????*????address值上,并增加指向PGD的指針pgd。
?????????*????重復這個循環(huán),直到所有指向非連續(xù)內(nèi)存區(qū)的頁表項都設(shè)置好。
?????????*/
????????next?=?(address?+?PGDIR_SIZE)?&?PGDIR_MASK;
????????if?(next?end)
next=end;
if(map_area_pud(pud,address,next,prot,pages)){
err=-ENOMEM;
break;
}

address=next;
pgd++;
}

spin_unlock(&init_mm.page_table_lock);
flush_cache_vmap((unsignedlong)area->addr,end);
returnerr;
}

map_area_pud()對PUD指向的所有頁表也執(zhí)行相似的循環(huán):

do{
pmd_t*pmd=pmd_alloc(&init_mm,pud,address);
if(!pmd)
return-ENOMEM;
if(map_area_pmd(pmd,address,end-address,prot,pages))
return-ENOMEM;
address=(address+PUD_SIZE)&PUD_MASK;
pud++;
}while(address

map_area_pmd()對PMD指向的所有頁表也執(zhí)行相似的循環(huán):

do{
pte_t*pte=pte_alloc_kernel(&init_mm,pmd,address);
if(!pte)
return-ENOMEM;
if(map_area_pte(pte,address,end-address,prot,pages))
return-ENOMEM;
address=(address+PMD_SIZE)&PMD_MASK;
pmd++;
}while(address

pte_alloc_kernel()函數(shù)分配一個新頁表,并更新PMD頁中間目錄的對應(yīng)表項。接下來,調(diào)用map_area_pte()為新頁表中的每一項分配物理頁幀。變量address的值增加2^22(正好是一個PMD頁表中一項跨越的線性地址范圍。

map_area_pte()主要工作是:

do{
structpage*page=**pages;
set_pte(pte,mk_pte(page,prot));
address+=PAGE_SIZE;
pte++;
(*pages)++;
}while(address

要映射的頁幀的頁描述符地址page從地址pages的變量所指向的數(shù)組項中讀取。新頁幀的物理地址通過set_pte和mk_pte宏寫入頁表。在為地址添加常數(shù)4096(頁幀的長度)后,重復這個循環(huán)。

注意,map_vm_area()還沒有修改當前進程的頁表。因此,當內(nèi)核態(tài)的進程訪問非連續(xù)內(nèi)存區(qū)域時,就會發(fā)生Page Fault,因為進程頁表中沒有該區(qū)域的映射關(guān)系。然而,Page Fault處理程序根據(jù)主內(nèi)核頁表(即init_mm.pgdPGD頁全局目錄及其子頁表)檢查錯誤的線性地址;一旦處理器發(fā)現(xiàn)一個主內(nèi)核頁表包含一個非空的地址項,它就把它的值復制到相應(yīng)進程的頁表項中,然后恢復進程的正常執(zhí)行。該機制在第9章的“頁面錯誤異常處理程序”一節(jié)中進行了描述。

除了vmalloc()之外,非連續(xù)內(nèi)存區(qū)的分配還可以由vmalloc_32()完成。它與vmalloc()類似,但是只分配ZONE_NORMAL和ZONE_DMA內(nèi)存區(qū)。

Linux v2.6還有一個vmap()函數(shù),它映射已經(jīng)在非連續(xù)內(nèi)存區(qū)中分配的頁幀:本質(zhì)上,這個函數(shù)接收一個指向頁描述符的指針數(shù)組作為它的參數(shù),調(diào)用get_vm_area()來獲得一個新的vm_struct描述符,然后調(diào)用map_vm_area()來映射頁幀。因此,該函數(shù)類似于vmalloc(),但它不分配頁幀。

所以說,vmalloc和vmap的操作,大部分的邏輯是一樣的,比如從VMALLOC_START ~ VMALLOC_END非連續(xù)物理內(nèi)存映射區(qū)之間查找并分配vmap_area。不同之處,在于vmap建立映射時,page是函數(shù)傳入進來的,而vmalloc是通過調(diào)用alloc_page接口向Buddy系統(tǒng)申請分配的。

4 釋放非連續(xù)內(nèi)存區(qū)

vfree()函數(shù)釋放由vmalloc()或vmalloc_32()創(chuàng)建的非連續(xù)內(nèi)存區(qū)域,而vunmap()函數(shù)釋放由vmap()創(chuàng)建的內(nèi)存區(qū)域。兩個函數(shù)都有一個參數(shù)-待釋放區(qū)域的初始線性地址的地址;它們都依賴于__vunmap()函數(shù)來完成實際的工作。

__vunmap()函數(shù)接收兩個參數(shù):要釋放的區(qū)域的初始線性地址的地址addr和標志deallocate_pages,如果在該區(qū)域中映射的頁幀應(yīng)該被釋放到ZONE頁幀分配器(vfree()調(diào)用),則設(shè)置該標志,否則將被清除(vunmap()調(diào)用)。該函數(shù)的主要功能如下:

void__vunmap(void*addr,intdeallocate_pages)
{
//...省略
/*1.獲取vm_struct描述符的地址;
*解除非連續(xù)物理內(nèi)存與線性地址在頁表中的映射關(guān)系。
*/
area=remove_vm_area(addr);
if(unlikely(!area)){
//...省略
return;
}

if(deallocate_pages){
inti;

/*
*2.掃描頁描述符指針數(shù)據(jù);對數(shù)組每個元素調(diào)用__free_page(),
*將頁幀釋放回`ZONE`頁幀分配器中。
*/
for(i=0;inr_pages;i++){
//...省略
__free_page(area->pages[i]);
}

if(area->nr_pages>PAGE_SIZE/sizeof(structpage*))
vfree(area->pages);
else
/*釋放指針數(shù)組,因為它是從連續(xù)物理內(nèi)存中申請的,
*所以調(diào)用kfree
*/
kfree(area->pages);
}

/*3.釋放vm_struct描述符*/
kfree(area);
return;
}

remove_vm_area()執(zhí)行下面的循環(huán):

structvm_struct*remove_vm_area(void*addr)
{
structvm_struct**p,*tmp;

//申請鎖
write_lock(&vmlist_lock);
/*搜索從addr開始的內(nèi)核虛擬內(nèi)存區(qū)域,
*找到要釋放的線性地址區(qū)域area
*/
for(p=&vmlist;(tmp=*p)!=NULL;p=&tmp->next){
if(tmp->addr==addr)
gotofound;
}
write_unlock(&vmlist_lock);
returnNULL;

found:
/*釋放area*/
unmap_vm_area(tmp);
*p=tmp->next;
write_unlock(&vmlist_lock);
returntmp;
}
write_lock(&vmlist_lock);
for(p=&vmlist;(tmp=*p);p=&tmp->next){
if(tmp->addr==addr){
unmap_vm_area(tmp);
*p=tmp->next;
break;
}
}
write_unlock(&vmlist_lock);
returntmp;

map_vm_area()函數(shù)的內(nèi)容如下所示,執(zhí)行與map_vm_area()函數(shù)相逆的過程:

address=area->addr;
end=address+area->size;
pgd=pgd_offset_k(address);

for(i=pgd_index(address);i<=?pgd_index(end-1);?i++)?{
????next?=?(address?+?PGDIR_SIZE)?&?PGDIR_MASK;
????if?(next?<=?address?||?next?>end)
next=end;
unmap_area_pud(pgd,address,next-address);
address=next;
pgd++;
}

繼而,unmap_area_pud()執(zhí)行與map_area_pud()相逆的過程:

do{
unmap_area_pmd(pud,address,end-address);
address=(address+PUD_SIZE)&PUD_MASK;
pud++;
}while(address&&(address

unmap_area_pmd()執(zhí)行與map_area_pmd()相逆的過程:

do{
unmap_area_pte(pmd,address,end-address);
address=(address+PMD_SIZE)&PMD_MASK;
pmd++;
}while(address

最后,unmap_area_pte()執(zhí)行與map_area_pte()相逆的過程:

do{
pte_tpage=ptep_get_and_clear(pte);
address+=PAGE_SIZE;
pte++;
if(!pte_none(page)&&!pte_present(page))
printk("Whee...Swappedoutpageinkernelpagetable
");
}while(address

在循環(huán)的每次迭代中,pte指向的頁表項被ptep_get_and_clear宏設(shè)置為0。

至于vmalloc(),內(nèi)核修改主內(nèi)核頁全局目錄及其子頁表的項(參見第2章的“內(nèi)核頁表”一節(jié)),但它保持進程頁表映射第4G的項不變。這很好,因為內(nèi)核永遠不會回收基于主內(nèi)核頁全局目錄的頁上目錄(PUD)、頁中間目錄(PMD)和頁表。

例如,假設(shè)內(nèi)核態(tài)進程訪問了一個非連續(xù)內(nèi)存區(qū)域,該內(nèi)存區(qū)域隨后被釋放。進程的PGD項等于主內(nèi)核PGD的相應(yīng)項,這要歸功于第9章“Page Fault異常處理程序”一節(jié)中解釋的機制;它們指向相同的頁上目錄、頁中間目錄和頁表。unmap_area_pte()函數(shù)只清除頁表的項(不回收頁表本身)。由于頁表項為空,進程對釋放的非連續(xù)內(nèi)存區(qū)域的進一步訪問將觸發(fā)Page fault。然而,處理程序會認為這樣的訪問是一個錯誤,因為主內(nèi)核頁表不包括有效的項。

5 vmalloc和kmalloc

到現(xiàn)在,我們應(yīng)該能清楚vmalloc和kmalloc的差異了吧,kmalloc會根據(jù)申請的大小來選擇基于slab分配器或者基于buddy系統(tǒng)來申請連續(xù)的物理內(nèi)存。而vmalloc則是通過alloc_page申請order = 0的頁面,再映射到連續(xù)的虛擬空間中,物理地址不連續(xù)。此外vmalloc可以休眠,不應(yīng)在中斷處理程序中使用。與vmalloc相比,kmalloc使用ZONE_DMA和ZONE_NORMAL空間,性能更快,缺點是連續(xù)物理內(nèi)存空間的分配容易帶來碎片問題,讓碎片的管理變得困難。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1346

    瀏覽量

    40152
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11161

    瀏覽量

    208461
  • 內(nèi)存管理
    +關(guān)注

    關(guān)注

    0

    文章

    168

    瀏覽量

    14106

原文標題:Linux內(nèi)核8.8-內(nèi)存管理之內(nèi)核非連續(xù)物理內(nèi)存分配

文章出處:【微信號:嵌入式ARM和Linux,微信公眾號:嵌入式ARM和Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Linux內(nèi)存管理是什么,Linux內(nèi)存管理詳解

    Linux內(nèi)存管理 Linux內(nèi)存管理是一個非常復雜的過程,主要分成兩個大的部分:
    的頭像 發(fā)表于 05-11 17:54 ?5899次閱讀
    <b class='flag-5'>Linux</b>的<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>是什么,<b class='flag-5'>Linux</b>的<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>詳解

    Linux內(nèi)核之內(nèi)存映射原理分析

    Linux 內(nèi)核采用延遲分配物理內(nèi)存的策略,在進程第一次訪問虛擬頁的時候,產(chǎn)生缺頁異常。如果是文件映射,那么
    發(fā)表于 07-21 17:06 ?2323次閱讀

    Linux內(nèi)核物理內(nèi)存組織結(jié)構(gòu)詳解

    Linux內(nèi)存管理子系統(tǒng)使用 節(jié)點(node)、區(qū)域(zone)和頁(page) 三級結(jié)構(gòu)描述物理內(nèi)存。
    發(fā)表于 08-21 15:35 ?511次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的<b class='flag-5'>物理</b><b class='flag-5'>內(nèi)存</b>組織結(jié)構(gòu)詳解

    Linux內(nèi)核內(nèi)存管理詳解

    內(nèi)存管理的主要工作就是對物理內(nèi)存進行組織,然后對物理內(nèi)存
    發(fā)表于 08-31 14:46 ?674次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>詳解

    Linux內(nèi)核內(nèi)存規(guī)整總結(jié)

    分配需求,如下圖所示: 內(nèi)存外部碎片導致實際占用物理頁不多,但是已無法申請>=4個頁連續(xù)內(nèi)存,理想當中我們希望
    的頭像 發(fā)表于 11-11 11:17 ?1205次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b><b class='flag-5'>內(nèi)存</b>規(guī)整總結(jié)

    Linux內(nèi)核內(nèi)存管理架構(gòu)解析

    內(nèi)存管理子系統(tǒng)可能是linux內(nèi)核中最為復雜的一個子系統(tǒng),其支持的功能需求眾多,如頁面映射、頁面分配、頁面回收、頁面交換、冷熱頁面、緊急頁面
    的頭像 發(fā)表于 01-04 09:24 ?589次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>架構(gòu)解析

    Linux內(nèi)核內(nèi)存管理之ZONE內(nèi)存分配

    內(nèi)核中使用ZONE分配器滿足內(nèi)存分配請求。該分配器必須具有足夠的空閑頁幀,以便滿足各種內(nèi)存大小請
    的頭像 發(fā)表于 02-21 09:29 ?815次閱讀

    Linux內(nèi)存系統(tǒng): Linux 內(nèi)存分配算法

    的大小· 它們的物理地址是連續(xù)的· 頁塊大小相同4、如何分配 4M 以上內(nèi)存?1) 為何限制大塊內(nèi)存分配
    發(fā)表于 08-24 07:44

    Linux虛擬內(nèi)存物理內(nèi)存的深刻分析

    的對象。vmalloc機制vmalloc機制使得內(nèi)核通過連續(xù)的線性地址來訪問連續(xù)物理頁框,這樣可以最大限度的使用高端
    發(fā)表于 05-31 08:00

    LINUX內(nèi)核中的內(nèi)存是如何進行分配

    size);size:待分配內(nèi)存的大小,自動按頁對齊。默認在動態(tài)內(nèi)存映射區(qū)分配。分配內(nèi)存在內(nèi)核
    發(fā)表于 11-04 14:46

    LINUX源代碼分析-內(nèi)存管理

    操作系統(tǒng)管理系統(tǒng)所有的物理空間, 現(xiàn)代大多數(shù)操作系統(tǒng)都采取多級管理, 即頁面級分配內(nèi)核內(nèi)存
    發(fā)表于 12-19 16:38 ?102次下載
    <b class='flag-5'>LINUX</b>源代碼分析-<b class='flag-5'>內(nèi)存</b><b class='flag-5'>管理</b>

    內(nèi)核內(nèi)存分配常用函數(shù)使用

    在 VMALLOC_START~4GB之間,這段連續(xù)內(nèi)存區(qū)映射到物理內(nèi)存也可能是非連續(xù)的在
    發(fā)表于 04-02 14:32 ?972次閱讀

    鴻蒙內(nèi)核源碼分析: 虛擬內(nèi)存物理內(nèi)存是怎么管理

    到哪是屬于什么段。這些值大小取決實際項目內(nèi)存條的大小,不同的內(nèi)存條,地址肯定會不一樣,所以必須由外部提供,鴻蒙內(nèi)核采用了Linux的段管理
    發(fā)表于 11-23 11:45 ?19次下載
    鴻蒙<b class='flag-5'>內(nèi)核</b>源碼分析: 虛擬<b class='flag-5'>內(nèi)存</b>和<b class='flag-5'>物理</b><b class='flag-5'>內(nèi)存</b>是怎么<b class='flag-5'>管理</b>的

    Linux內(nèi)核深度解析》之內(nèi)存地址空間

    內(nèi)核空間提供了把頁劃分成小內(nèi)存分配的塊分配器,提供分配內(nèi)存的接口 kmalloc()和釋放
    的頭像 發(fā)表于 07-15 14:22 ?2222次閱讀

    Linux內(nèi)核引導內(nèi)存分配器的原理

    Linux內(nèi)核引導內(nèi)存分配器使用的是伙伴系統(tǒng)算法。這種算法是一種用于動態(tài)內(nèi)存分配的高效算法,它將
    發(fā)表于 04-03 14:52 ?363次閱讀