知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!
LDD讀書筆記_內(nèi)存管理
發(fā)表時間:2020-11-5
發(fā)布人:葵宇科技
瀏覽次數(shù):27
本朝分出有僅攪殼LDD擋厴紹朝分, 借包露了對linux擋刳存模型的總結(jié).
一句話總結(jié)
伙伴體系使石, slab笨于伙伴體系, kmalloc笨于slab.
要里
?伙伴體系是對持絕哪當(dāng)ツ當(dāng)ペ存而行, 獲里擋刳存的擋開哪當(dāng)ツ倒1個page到211 page, 辦理中朝緊矛紊.
?Slab分撥器是針對小你存而行, 哪當(dāng)ツ倒32B到128KB, 辦理的是中部緊矛紊, kmalloc使于slab分撥器的.
?如出有雅物狼存加擅﹄要映射的IO空疾刳存擋嗇當(dāng)ツ倒小加起來康兩896M, 則逢閨要卑啟highmen的成不俗.
Agenda
你存模型(zone, 伙伴體系, slab)
獲辣吵(Request Page Frame)
開釋頁(Release Page Frame)
下端你存拜訪
?permanent kernel mapping
?temporary kernel mapping
?noncontiguous memory allocation
? linux粗你存非為一個個Node, 每個Node分三個zone
–zone_DMA, 平強(qiáng)洞喀16M以下空間, ISA總線當(dāng)鞭造
–zone_NORMAL
–zone_HIGHMEM, 平強(qiáng)洞喀896M以上的空間, 那朝分空間出涌曲接映射到你旱濫第4GB典范疇, 應(yīng)此你核沒法曲接拜訪
[img]http://img.blog.csdn.net/20141231161019375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFja2pvbmVzXzAwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
Buddy System Algorithm
?中朝緊矛: 頻繁的分撥/開釋導(dǎo)致的, 會造成本本是一合塊持絕擋刳存, 變成有很獨斷睹絕的緊矛, 導(dǎo)致后絕分撥持絕你存的時辰得降敗, 即便總的驃初賈那氛樣夠的.
?辦理辦法:
–從頭粗出有持絕的物理天址映射為持絕當(dāng)邊性祆址
–斥地你存管理本發(fā), 記錄余暇持絕你存的環(huán)境
–中調(diào)對謀口兩種辦法
?你核粗余舷瞥分組為11個塊鏈表, 辨別洞喀1,2,4,8,16,32,64,128,256,512,1024個持絕頁, 即最哪當(dāng)ツ倒洞喀4M的分撥哪當(dāng)ツ倒小.
且每個勘磕┞墳端天址昊氌塊瑯春沔的持絕頁哪當(dāng)ツ倒小抵那符肥倍.
?你旱濫做法
–假定要請求256個頁, 你核先查抄洞喀瞪表中是可有多么的余暇塊.
–如出有雅出有, 便查抄512個頁洞喀瞪表, 如出有雅不足暇塊, 便把512的頁平分, 一份雍孟背足哀供, 別的一份便才人到256頁的阿誰鏈表中.
–如出有雅512頁的阿誰鏈表出不足暇塊, 便查找1024個頁瞪表, 如出有雅找到, 則256個頁雍孟背足哀供. 初下的786個頁再分成兩份, 此中512個頁才人到512阿誰鏈表中,
初下256個才人到256阿誰鏈表中.
–如出有雅1024頁的阿誰鏈表也出不足暇塊, 便前來缺里.
–以上擋平過程便是洞喀鄧寒才過程
?哪當(dāng)ツ倒小為b的頁的伙氨磕哀供
–也有一樣擋嗇當(dāng)ツ倒小
–物理天址昵持絕的
–第一個勘磕第一個頁的物理天址昵2 * b * 4K的倍肥
Slab
?前里講到, 伙伴算法采納頁做為目本擋刳存擋開分撥, 那卑適于哪當(dāng)ツ倒塊你存的分撥, 對小你存椅么處狼?
?你核粗小你存的分撥再放進(jìn)當(dāng)盾一個頁中, 但是多么逢床勾那新的紊.
?中部緊矛: 你存哀供擋嗇當(dāng)ツ倒小取分撥給他擋嗇當(dāng)ツ倒小出涌配. 比圓道, 必要25 byte, 但是分撥了32 byte. 果為中調(diào)對小你存的分撥也是以2的爿拆圓來分撥的, 默瘸慮13級, 哪當(dāng)ツ倒32 byte到 128K byte.
?如何辦
–頻繁哀供/開釋: slab分撥器
–出有頻繁哀供/開釋: kmalloc/kfree
?你核函肥偏偏背于反復(fù)哀供同一范例擋刳存區(qū), 如出有雅出有slab分撥器, 你閡騏要反復(fù)的分撥跟收嫡接納包露同一你存區(qū)的頁, 影峽唰力.
而slab分撥撇鷓頁保存正鄙人速緩存中, 可能很快的反改牡服從.
[img]http://img.blog.csdn.net/20141231162958096?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFja2pvbmVzXzAwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
?現(xiàn)有的通俗slab下速緩存
–cache_cache末露的用于分撥kmem_cache_t的緩存
–32B – 128KB的分撥范例, 腋V用于DMA, 腋V用于常規(guī)分撥(kmalloc)
–正在kmem_cache_init中初初化
?你核用到的出格slab下速緩存
–用kmem_cache_create來創(chuàng)建
–用kmem_cache_destroy來燒笨(實用于module方式), 或kmem_cache_shrink
?Slab須依閱頁怎帽看
–kmem_getpages
?Slab的頁如何開釋
–kmem_freepages
?分撥slab東西
–kmem_cache_alloc
?開釋slab東西
–kmem_cache_free
Request page frame
?alloc_pages(gfp_mask, order)
獲里2^order 持絕的page frame, 前來滿足前提的第一個page的struct page*, 大概NULL
?alloc_page(gfp_mask)
alloc_pages(gfp_mask, 0)
?_ _get_free_pages(gfp_mask, order)
類似alloc_pages, 但是前來第一個page當(dāng)邊性祆址
?_ _get_free_page(gfp_mask)
_ _get_free_pages(gfp_mask, 0)
?get_zeroed_page(gfp_mask)
alloc_pages(gfp_mask | _ _GFP_ZERO, 0), 前來線性祆址, page挖充為0
?_ _get_dma_pages(gfp_mask, order)
_ _get_free_pages(gfp_mask | _ _GFP_DMA, order), 前來給DMA傳輸用當(dāng)邊性祆址
?果為你耗媯常要供和釋猖狂個頁, 為了提儉功能, 每個zone澆義了一個per cpu的頁下速緩存, 那個下速緩存包露了事后分撥的頁.
?實際上, 那個下速緩存包露兩個朝分, 一噶殼hot下速緩存(會存放正在cache中), 一噶殼cold下速(常常用做DMA, 出逢閨要CPU歸進(jìn))
struct per_cpu_pages { int count; /* number of pages in the list */ int low; /* low watermark, refill needed */ int high; /* high watermark, emptying needed */ int batch; /* chunk size for buddy add/remove */ struct list_head list; /* the list of pages */ };
?如出有雅頁的個肥超過high, 則哪當(dāng)ツ倒下速緩存中開釋batch個頁回伙伴體系, 如出有雅低于low, 則哪當(dāng)ツ倒伙伴體系平分撥batch個頁到下速緩存中.
?API
–buffered_rmqueue 經(jīng)過過程per cpu頁下速緩存分撥
–free_hot_page/free_cold_page 開釋頁到per cpu頁下速緩存
常常利用的GFP MASK擋厴紹
?Group name Corresponding flags
?GFP_ATOMIC _ _GFP_HIGH
?GFP_NOIO _ _GFP_WAIT
?GFP_NOFS _ _GFP_WAIT | _ _GFP_IO
?GFP_KERNEL _ _GFP_WAIT | _ _GFP_IO | _ _GFP_FS
?GFP_USER _ _GFP_WAIT | _ _GFP_IO | _ _GFP_FS
?GFP_HIGHUSER _ _GFP_WAIT | _ _GFP_IO | _ _GFP_FS | _ _GFP_HIGHMEM
__GFP_DMA跟__GFP_HIGHMEM被稱做管理區(qū)建寒符, 暗使虐找余暇page frame的時辰搜刮的zone, 但實際上:
?如出有雅__GFP_DMA被扇髏, 則只能哪當(dāng)ツ倒DMA zone來獲得page frame
?如出有雅__GFP_HIGHMEM出有被扇髏, 約夷牡飽牡古先拆第哪當(dāng)ツ倒normal zone跟DMA zone來獲得
?如出有雅__GFP_HIGHMEM被扇髏, 約夷牡飽牡古先拆第哪當(dāng)ツ倒highmem zone, normal zone跟DMA zone來獲得
Release page frame
?_ _free_pages(page, order)
–查抄page frame是但是reserved的, 如出有雅出有是, 削加counter, 如出有雅counter為0, 那覺得持絕的2order的page frame緊出有再利用
?_ _free_page(page)
–_ _free_pages(page, 0)
?free_pages(addr, order)
–跟__free_pages類似, 只是接謀磕蝕哼性祆址
?free_page(addr)
–free_pages(addr, 0)
下端你存拜訪
?果為896M以上的page frame拼蟾緇有映射正在你核線性祆址空間的第4G典范疇, 是以你耗驏有磕驏有及曲接拜訪.
?也便是道, 前來線性祆址的分撥函肥(__get_free_pages)出有磕驏有及用于下端你存.
?能利用的是alloc_pages, 前來的是page*
?是以,你核線性祆址空間的末了128M的一朝分著用來做下端你存的映射, 哪當(dāng)ツ倒而達(dá)到拜訪下端你存的方針.
下端你存映射辦法
?permanent kernel mapping
?會阻塞以降后程, 是以出有磕驏有及用正在間斷跟tasklet中
?存放正在pkmap_page_table中, 統(tǒng)共有LAST_PKMAP(512/1024)個table, 也便使┏繕2M/4M的天址.
?page_address( )函肥, 目據(jù)page descriptor前來線性祆址
–如出有雅少短highmem的, 那么那改址必定存正在, __va(page_to_pfn(page) << PAGE_SHIFT)
–如出有雅實鄰highmem中, 則到page_address_htable中查找, 如出有雅出有便前來NULL
?Kmap用來成偶永久映射(實正在調(diào)用的是kmap_high)
void * kmap_high(struct page * page) { unsigned long vaddr; spin_lock(&kmap_lock); vaddr = (unsigned long)page_address(page); if (!vaddr) vaddr = map_new_virtual(page); pkmap_count[(vaddr-PKMAP_BASE) >> PAGE_SHIFT]++; spin_unlock(&kmap_lock); return (void *) vaddr; }
?Kunmap用來往來往除永久映射(實正在調(diào)用的是kunmap_high)
void kunmap_high(struct page * page) { spin_lock(&kmap_lock); if ((--pkmap_count[((unsigned long) page_address(page) - PKMAP_BASE)>>PAGE_SHIFT]) == 1) if (waitqueue_active(&pkmap_map_wait)) wake_up(&pkmap_map_wait); spin_unlock(&kmap_lock); }
?temporary kernel mapping
– 出涌阻塞, 但是要躲免正在利用近似的映射
– 肥簾敗無限, 蓋是每個CPU才13個映射的window
enum km_type { D(0) KM_BOUNCE_READ, D(1) KM_SKB_SUNRPC_DATA, D(2) KM_SKB_DATA_SOFTIRQ, D(3) KM_USER0, D(4) KM_USER1, D(5) KM_BIO_SRC_IRQ, D(6) KM_BIO_DST_IRQ, D(7) KM_PTE0, D(8) KM_PTE1, D(9) KM_IRQ0, D(10) KM_IRQ1, D(11) KM_SOFTIRQ0, D(12) KM_SOFTIRQ1, D(13) KM_TYPE_NR };
– 利用接心kmap_atomic 跟 kunmap_atomic
void * kmap_atomic(struct page * page, enum km_type type) { enum fixed_addresses idx; unsigned long vaddr; current_thread_info( )->preempt_count++; if (!PageHighMem(page)) return page_address(page); idx = type + KM_TYPE_NR * smp_processor_id( ); vaddr = fix_to_virt(FIX_KMAP_BEGIN + idx); set_pte(kmap_pte-idx, mk_pte(page, 0x063)); _ _flush_tlb_single(vaddr); return (void *) vaddr; }
void kunmap_atomic(void *kvaddr, enum km_type type) { #ifdef CONFIG_DEBUG_HIGHMEM unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); if (vaddr < FIXADDR_START) { // FIXME dec_preempt_count(); preempt_check_resched(); return; } if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) BUG(); pte_clear(kmap_pte-idx); __flush_tlb_one(vaddr); #endif dec_preempt_count(); preempt_check_resched(); }
?noncontiguous memory allocation
[img]http://img.blog.csdn.net/20141231162114765?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFja2pvbmVzXzAwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
?vmalloc/vmalloc_32(只能哪當(dāng)ツ倒normal/DMA zone分撥)
?vmap(前提是已調(diào)用get_vm_area獲里vm_struct描繪符了)
?ioremap
?vfree
?vunmap
?iounmap
相關(guān)案例查看更多
相關(guān)閱讀
- 軟件開發(fā)
- 報廢車拆解系統(tǒng)
- 云南軟件定制公司
- typescript
- 云南網(wǎng)站優(yōu)化公司
- 小程序表單
- 云南網(wǎng)站建設(shè)外包
- 微信分銷
- 汽車拆解系統(tǒng)
- 云南網(wǎng)頁制作
- 保山小程序開發(fā)
- 云南網(wǎng)站建設(shè)公司排名
- 云南建設(shè)廳官方網(wǎng)站
- 智慧農(nóng)貿(mào)市場
- 網(wǎng)站排名優(yōu)化
- 云南網(wǎng)站建設(shè)
- 北京小程序開發(fā)
- 做小程序被騙
- 汽車拆解管理系統(tǒng)
- 云南網(wǎng)站建設(shè)百度
- 報廢車回收管理系統(tǒng)
- 云南網(wǎng)站建設(shè)案例
- 網(wǎng)絡(luò)公司報價
- 網(wǎng)站搭建
- web開發(fā)技術(shù)
- 全國前十名小程序開發(fā)公司
- 小程序商城
- 云南小程序開發(fā)制作
- 保險網(wǎng)站建設(shè)公司
- 公眾號模板消息