c++ mmap写入速度_内存管理(24)mmap和缺页中断
生活随笔
收集整理的這篇文章主要介紹了
c++ mmap写入速度_内存管理(24)mmap和缺页中断
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
相關文件:
mm/mlock.c
mm/util.c
mm/mmap.c
include/linux/slab.h
mmap系統調用陷入內核中會調用vm_mmap_pgoff=>do_mmap_pgoff函數來真正完成mmap操作
1.1.do_mmap_pgoff函數(關鍵部分代碼)
do_mmap_pgoff
- 16行:對需要映射的內存長度頁對齊
- 20行:get_unmapped_area返回需要映射的地址空間
- 25行:建立映射關系,如果定義了VM_LOCKED還要立即申請物理內存,該函數的實現細節請看1.2小節
1.2.mmap_region函數(關鍵部分代碼)
mmap_region
- 40行:查找符合條件的vma
- 46行:合并相鄰的vma
- 49行:如果沒找到合適的vma則調用kmem_cache_zalloc申請一個vma結構,這個函數前面也說過
- 51行:把初始化好的vma插入mm下的內存管理樹結構
- 55行:配置vma的訪問權限
2.缺頁中斷(armv7架構)
相關文件:
mm/memory.c
arch/arm/mm/fault.c
缺頁中斷與具體的處理器架構密切相關。以ARM為例,頁面轉換失效和頁面訪問權限失效對應的核心處理函數為do_page_fault。
缺頁中斷基本流程
2.1.do_page_fault函數(關鍵部分)
do_page_fault函數-1
- 69行:處于中斷上下文或者禁止搶占時跳轉到no_context標簽
- 71行:用戶空間添加FAULT_FLAG_USER標志
- 73行:具備FSR_WRITE權限則添加FAULT_FLAG_WRITE標志
- 76行:真正處理缺頁中斷的函數,詳情看小節2.2
do_page_fault函數-2
- 85行:不屬于以上異常就說明缺頁中斷正常處理完成
- 88行:缺頁中斷處理有異常發生,如果是內核空間跳轉到no_context標簽執行__do_kernel_fault函數
- 90行:VM_FAULT_OOM則調用pagefault_out_of_memory發送OOM信號
- 95行:用戶空間則向進程發送SIGSEGV信號,進程中斷
- 99行:__do_kernel_fault函數發送Oops錯誤
2.2.__do_page_fault函數(關鍵部分)
__do_page_fault函數
- 112行:查找vma
- 115行:vma訪問權限
- 120行:缺頁中斷處理,詳見2.3
2.3.__handle_mm_fault函數(關鍵部分)
__handle_mm_fault函數
- 141~148行:獲取到addr所對應的PGD、PUD、PMD、PTE
- 150行:handle_pte_fault處理缺頁中斷,詳見2.4
2.4.handle_pte_fault函數(關鍵部分)
handle_pte_fault函數-1
176行:如果頁面不在內存中(還未映射真正的頁),調用pte_none177行:頁面為空。對于文件映射通常會調用do_fault(詳見2.6);否則表示匿名映射則會調用do_anonymous_page(詳見2.5)186行:頁面不為空,表示正處于交換內存中,調用do_swap_page函數,詳見2.7189行:寫異常190行:如果pte為只讀權限,調用do_swap_page函數193行:如果具備寫屬性,L_PTE_DIRTY置位handle_pte_fault函數-2
- 189行:設置L_PTE_YONG位
- 190行:如果pte頁面項有變化就要寫入物理頁面項,并更新TLB cache
2.5.do_anonymous_page函數
do_anonymous_page函數-1
- 225行:判斷當前VMA是否需要增加一個guard page作為安全墊
- 229~236行:對于只讀的VMA,系統使用0號頁面生成新的PTE entry,0號頁面是在paging_init中初始化的,前面提過。使用pte_offset_map_lock能得到頁表項。如果表項不為空則跳轉到setpte處更新到硬件表中。
do_anonymous_page函數-2
241行:分配一個可寫的匿名頁面,最終調用伙伴系統的alloc_pages,優先選擇高端內存254~256行:通過mk_xxx生成一個新的pte entry262行:inc_mm_counter_fast增加系統中匿名頁面的引用計數263行增加到RMAP反向映射系統中265行:把匿名頁添加到LRU鏈表中,kswap中會用到267行:設置pte entry到硬件頁表中do_anonymous_page函數-3
- 270行:刷新TLB和cache
2.6.do_fault函數
do_fault函數
- 300行:只讀缺頁異常,詳見2.8小節
- 303行:私有映射且發生寫時拷貝缺頁異常,詳見2.9小節
- 305行:公有映射寫缺頁異常,詳見2.10小節
2.7.do_swap_page函數
與2.8和2.9類似
2.8.do_read_fault函數
static int do_read_fault(struct mm_struct *mm, struct vm_area_struct *vma,unsigned long address, pmd_t *pmd,pgoff_t pgoff, unsigned int flags, pte_t orig_pte){struct page *fault_page;if (vma->vm_ops->map_pages && fault_around_bytes >> PAGE_SHIFT > 1) {//拿到缺頁異常地址addr所對應的ptepte = pte_offset_map_lock(mm, pmd, address, &ptl);/*以缺頁異常地址為中心,從start_addr開始檢查相應的pte是否為空,若為*空則從這個pte開始到max_pgoff為止使用map_pages()來映射PTE。這么做為*了提前建立缺頁地址(進程地址空間)與(現存)page cache的映射關系,*減少缺頁中斷的次數從而提高效率。*/do_fault_around(vma, address, pte, pgoff, flags);//頁面內容在剛剛被系統修改了,跳轉到unlock_out標簽if (!pte_same(*pte, orig_pte))goto unlock_out;pte_unmap_unlock(pte, ptl);}//為缺頁異常地址分配page cache ret = __do_fault(vma, address, pgoff, flags, NULL, &fault_page);if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY)))return ret;//拿到映射好的缺頁地址的PTEpte = pte_offset_map_lock(mm, pmd, address, &ptl);if (unlikely(!pte_same(*pte, orig_pte))) {pte_unmap_unlock(pte, ptl);unlock_page(fault_page);page_cache_release(fault_page);return ret;}//為PTE創建條目,并加入反向映射機制do_set_pte(vma, address, fault_page, pte, false, false);unlock_page(fault_page);unlock_out://放棄映射pte_unmap_unlock(pte, ptl);return ret;}2.9.do_cow_fault函數
//省略部分錯誤判斷static int do_cow_fault(struct mm_struct *mm, struct vm_area_struct *vma,unsigned long address, pmd_t *pmd,pgoff_t pgoff, unsigned int flags, pte_t orig_pte){pte_t *pte;int ret;if (unlikely(anon_vma_prepare(vma)))return VM_FAULT_OOM;//以GFP_HIGHUSER_MOVABLE分配掩碼分配一個物理頁面new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);if (mem_cgroup_try_charge(new_page, mm, GFP_KERNEL, &memcg)) {page_cache_release(new_page);return VM_FAULT_OOM;}//讀取文件內容到fault_pageret = __do_fault(vma, address, pgoff, flags, new_page, &fault_page);if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY)))goto uncharge_out;if (fault_page)//拷貝內容到物理頁面copy_user_highpage(new_page, fault_page, address, vma);__SetPageUptodate(new_page);//取得對應的PTEpte = pte_offset_map_lock(mm, pmd, address, &ptl);//為對應PTE創建條目再添加到反向映射機制do_set_pte(vma, address, new_page, pte, true, true);mem_cgroup_commit_charge(new_page, memcg, false);//物理頁面加入LRU隊列進行管理,內存回收會用到lru_cache_add_active_or_unevictable(new_page, vma);pte_unmap_unlock(pte, ptl);if (fault_page) {unlock_page(fault_page);page_cache_release(fault_page);} else {i_mmap_unlock_read(vma->vm_file->f_mapping);}return ret;uncharge_out:mem_cgroup_cancel_charge(new_page, memcg);page_cache_release(new_page);return ret;}2.10.do_shared_fault函數
與2.8和2.9類似
2.11.do_fault_around函數
static void do_fault_around(struct vm_area_struct *vma, unsigned long address,pte_t *pte, pgoff_t pgoff, unsigned int flags){unsigned long start_addr, nr_pages, mask;pgoff_t max_pgoff;struct vm_fault vmf;int off;/*fault_around_bytes是一個全局變量,等于16個page的大小,所以此處nr_pages=16*/nr_pages = ACCESS_ONCE(fault_around_bytes) >> PAGE_SHIFT;//以16頁對齊為步長計算掩碼mask = ~(nr_pages * PAGE_SIZE - 1) & PAGE_MASK;//以16頁對齊,取缺頁地址和vm_start較大的那個為掃描PTE的起始地址start_addr = max(address & mask, vma->vm_start);/*PTRS_PER_PTE 表示每個PTE項所對應的條目數,此處為512也就是1個PTE對應512頁*這一步相當于取缺頁地址和start_addr的偏離(頁數單位)的絕對值*/off = ((address - start_addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);//查找PTE的起始位置pte -= off;pgoff -= off;/* * max_pgoff is either end of page table or end of vma * or fault_around_pages() from pgoff, depending what is nearest. */max_pgoff = pgoff - ((start_addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +PTRS_PER_PTE - 1;max_pgoff = min3(max_pgoff, vma_pages(vma) + vma->vm_pgoff - 1,pgoff + nr_pages - 1);/* Check if it makes any sense to call ->map_pages */while (!pte_none(*pte)) {if (++pgoff > max_pgoff)return;start_addr += PAGE_SIZE;if (start_addr >= vma->vm_end)return;pte++;}//找到為空的PTE,則從此處開始到max_pgoff映射PTEvmf.virtual_address = (void __user *) start_addr;vmf.pte = pte;vmf.pgoff = pgoff;vmf.max_pgoff = max_pgoff;vmf.flags = flags;vma->vm_ops->map_pages(vma, &vmf);} 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的c++ mmap写入速度_内存管理(24)mmap和缺页中断的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电子科大沙河校区有计算机专业,电子科大沙
- 下一篇: 正则表达式提取器_C++11新特性7 -