真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯網站制作重慶分公司

八、內存管理(三)-創(chuàng)新互聯

3、非連續(xù)內存區(qū)管理

按需網站策劃可以根據自己的需求進行定制,成都網站制作、網站設計構思過程中功能建設理應排到主要部位公司成都網站制作、網站設計的運用實際效果公司網站制作網站建立與制做的實際意義

如果對內存區(qū)的請求不是很頻繁,那么,通過連續(xù)的線性地址來訪問非連續(xù)的頁框這樣一種分配模式就很有意義。這種模式的主要優(yōu)點是避免了外碎片,而缺點是必須打亂內核頁表。非連續(xù)內存區(qū)的大小必須是4096的倍數。linux在幾個方面使用非連續(xù)內存區(qū),例如,為活動的交換區(qū)分配數據結構,為模塊分配空間,或給某些IO驅動程序分配緩沖區(qū)。此外,非連續(xù)內存區(qū)還提供了另一種使用高端內存頁框的方法。

3.1 分連續(xù)內存區(qū)的線性地址

要查找一個線性地址的空閑區(qū),從PAGE_OFFSET開始查找,即第4個GB的其實地址

1、內存區(qū)的開始部分包含的是是對前896MB RAM進行映射的線性地址;直接映射的物理內存末尾多對應的線性地址保存在high_memory變量中。

2、內存區(qū)的結尾部分包含的是固定映射線性地址。

3、從PKMAP_BASE開始,我們查找用于高端內存頁框的永久內核映射的線性地址

4、其余的線性地址可以用于非連續(xù)內存區(qū)。在物理內存映射的末尾與第一個內存區(qū)之間插入一個大小為8MB的安全區(qū),目的是為了捕獲對內存的越界訪問。處于同樣的理由,插入其他4KB大小的安全區(qū)來隔離非連續(xù)內存區(qū)。為非連續(xù)內存區(qū)保留的線性地址空間的起始地址由VMALLOC_START宏定義,而末尾由VMALLOC_END宏定義

3.2 非連續(xù)內存區(qū)描述符

struct vm_struct{

void * addr;//內存區(qū)第一個內存單元的地址

unsigned long size; //內存區(qū)的大小加上4k隔離區(qū)的值

unsigned long flags; //非連續(xù)內存區(qū)映射的內存的類型

struct page ** pages; //非連續(xù)內存區(qū)包含的頁描述符數組

unsigned int nr_pages;//頁數量

unsigned long phys_addr;//該字段設為0,除非內存已被創(chuàng)建來映射一個硬件設備的IO共享內存

struct vm_struct * next;//指向下一個vm_struct結構的指針

}

flags字段標識了非連續(xù)區(qū)映射內存的類型:VM_ALLOC表示使用vmalloc()得到的頁,VM_MAP表示使用vmap()映射已經分配的頁,VM_IOREMAP表示ioremap()映射的硬件設備的板上內存。

get_vm_area()函數在線性地址VMALLOC_START和VMALLOC_END之間查找一個空閑區(qū)域。函數使用size和flag兩個參數,步驟如下:

1、調用kmalloc()為vm_struct類型的新描述符獲得一個內存區(qū)

2、得到vmlist_lock鎖,并掃描類型為vm_struct的描述符鏈表來查找線性地址的一個空閑區(qū)域,至少覆蓋size+4096個地址。

3、如果存在這樣一個區(qū)間,函數就初始化描述符字段,釋放vmlist_lock鎖,返回非連續(xù)內存區(qū)描述符的起始地址。

4、否則釋放描述符,釋放鎖,返回NULL

3.3 分配非連續(xù)內存區(qū)

vmalloc()函數給內核分配一個非連續(xù)內存區(qū),參數size表示所請求的內存區(qū)大小

void *vmalloc(unsigned long size){

struct vm_struct *area;

struct page **pages;

unsigned int array_size,i;

size = (size +PAGE_SIZE -1)&PAGE_MASK;

area = get_vm_area(size,VM_ALLOC);

if(!area)

return NULL;

area->nr_pages =size>>PAGE_SHIFT;

array_size =  (area->nr_pages *sizeof(struct page *));

area->pages = pages = kmalloc(array_size,GFP_KERNEL);

if(!area->pages){

remove_vm_area(area->addr);

kfree(area);

return NULL;

}

memset(area->pages,0,array_size);

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);

return NULL:

}

}

if(map_vm_area(area,__pgprot(0x63),&pages));

goto fail;

return area->addr;

}

map_vm_area(struct vm_struct * area,prot,struct page ** pages){

unsigned long address,end;

address = area->addr;

end = address+(area->size-PAGE_SIZE);

pgd = pgd_offset_k(address);//主內核頁全局目錄中的目錄項,該項對應于內存區(qū)其實線性地址

spin_lock(&init_mm.page_table_lock);//獲得內核頁表自旋鎖

int ret = 0;

for(i=pgd_index(address);i

pud_t *pud = pud_alloc(&init_mm,pgd,address);//為新的內存區(qū)創(chuàng)建一個頁上級目錄,并把它的物理地址寫入內核全局目錄的合適表項。然后調用alloc_area_pud()為新的頁上級目錄分配所有相關的頁表。

ret = -ENOMEM;

if(!pud) break;

next = (address + PGDIR_SIZE)&PGDIR_MASK;

if(nextend)

next = end;

if(map_area_pud(pud,address,next,prot,pages))

break;

address = next;

pgd++;

ret = 0;

}

map_area_pud():

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():

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

map_area_pte():

do{

struct page *page = **pages;

set_pte(pte,mk_pte(page,prot);

address += PAGE_SIZE;

pte++; 

(*pages)++;

}while(address

3.4 釋放非連續(xù)內存區(qū)

vfree-----vmalloc()、vmalloc32();

vunmap----vmap();

vfree和vunmap都依賴于__vunmap()函數。

__vunmap()接收兩個參數,將要釋放內存區(qū)的起始地址addr,以及標致deallocate_pages,如果被映射到內存區(qū)內的頁框應當被釋放到頁框分配器,這個標志設置;步驟:

1、調用remove_vm_area()函數得到vm_struct描述符的地址area,并清除內存區(qū)中線性地址對應的內核頁表項。

2、如果deallocate_pages被設置,函數掃描指向頁描述符的area->pages指針數組;對于數組的每一個元素,調用__free_page()函數釋放頁框到分區(qū)分配器。此外,執(zhí)行kfree(area->pages)來釋放數組本身。

3、調用kfree(area)來釋放vm_struct描述符

remove_vm_area():

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);

return tmp;

unmap_vm_area():

address = area->addr;

end = address +area->size;

pgd = pgd_offset_k(address);

for(i=pgd_index(address);i<=pgd_index(end);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():

do{

unmap_area_pmd(pud,address,end-address)

address = (address +PUD_SIZE)&PUD_MASK;

pud++;

}while(address&&(address

unmap_area_pmd():

do{

unmap_area_pte(pmd,address,end-address);

address = (address + PMD_SIZE)&PMD_MASK;

pmd++;

}while(address

unmap_area_pte():

do{

pte_t page = ptep_get_and_clear(pte);

address += PAGE_SIZE;

pte++;

if(!pte_none(page)&&!pte_present(page))

printk("Whee..Swapped out page in kermel page table ");

}while(address
網站標題:八、內存管理(三)-創(chuàng)新互聯
分享路徑:http://weahome.cn/article/djspej.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部