Linux内存page,【原创】(十四)Linux内存管理之page fault处理
背景
Read the fucking source code! --By 魯迅
A picture is worth a thousand words. --By 高爾基
說明:
Kernel版本:4.14
ARM64處理器,Contex-A53,雙核
使用工具:Source Insight 3.5, Visio
1. 概述
上篇文章分析到malloc/mmap函數(shù)中,內(nèi)核實現(xiàn)只是在進(jìn)程的地址空間建立好了vma區(qū)域,并沒有實際的虛擬地址到物理地址的映射操作。這部分就是在Page Fault異常錯誤處理中實現(xiàn)的。
Linux內(nèi)核中的Page Fault異常處理很復(fù)雜,涉及的細(xì)節(jié)也很多,malloc/mmap的物理內(nèi)存映射只是它的一個子集功能,下圖大概涵蓋了出現(xiàn)Page Fault的情況:
下邊就開始來啃啃硬骨頭吧。
2. Arm64處理
Page Fault的異常處理,依賴于體系結(jié)構(gòu),因此有必要來介紹一下Arm64的處理。
代碼主要參考:arch/arm64/kernel/entry.S。
Arm64在取指令或者訪問數(shù)據(jù)時,需要把虛擬地址轉(zhuǎn)換成物理地址,這個過程需要進(jìn)行幾種檢查,在不滿足的情況下都能造成異常:
地址的合法性,比如以39有效位地址為例,內(nèi)核地址的高25位為全1,用戶進(jìn)程地址的高25位為全0;
地址的權(quán)限檢查,這里邊的權(quán)限位都位于頁表條目中;
從上圖中可以看到,最后都會調(diào)到do_mem_abort函數(shù),這個函數(shù)比較簡單,直接看代碼,位于arch/arm64/mm/fault.c:
/*
* Dispatch a data abort to the relevant handler.
*/
asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
struct pt_regs *regs)
{
const struct fault_info *inf = esr_to_fault_info(esr);
struct siginfo info;
if (!inf->fn(addr, esr, regs))
return;
pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n",
inf->name, esr, addr);
mem_abort_decode(esr);
info.si_signo = inf->sig;
info.si_errno = 0;
info.si_code = inf->code;
info.si_addr = (void __user *)addr;
arm64_notify_die("", regs, &info, esr);
}
該函數(shù)中關(guān)鍵的處理:根據(jù)傳進(jìn)來的esr獲取fault_info信息,從而去調(diào)用函數(shù)。struct fault_info用于錯誤狀態(tài)下對應(yīng)的處理方法,而內(nèi)核中也定義了全局結(jié)構(gòu)fault_info,存放了所有的情況。
主要的錯誤狀態(tài)和處理函數(shù)對應(yīng)如下:
static const struct fault_info fault_info[] = {
{ do_bad,SIGBUS, 0,"ttbr address size fault"},
{ do_bad,SIGBUS, 0,"level 1 address size fault"},
{ do_bad,SIGBUS, 0,"level 2 address size fault"},
{ do_bad,SIGBUS, 0,"level 3 address size fault"},
{ do_translation_fault,SIGSEGV, SEGV_MAPERR,"level 0 translation fault"},
{ do_translation_fault,SIGSEGV, SEGV_MAPERR,"level 1 translation fault"},
{ do_translation_fault,SIGSEGV, SEGV_MAPERR,"level 2 translation fault"},
{ do_translation_fault,SIGSEGV, SEGV_MAPERR,"level 3 translation fault"},
{ do_bad,SIGBUS, 0,"unknown 8"},
{ do_page_fault,SIGSEGV, SEGV_ACCERR,"level 1 access flag fault"},
{ do_page_fault,SIGSEGV, SEGV_ACCERR,"level 2 access flag fault"},
{ do_page_fault,SIGSEGV, SEGV_ACCERR,"level 3 access flag fault"},
{ do_bad,SIGBUS, 0,"unknown 12"},
{ do_page_fault,SIGSEGV, SEGV_ACCERR,"level 1 permission fault"},
{ do_page_fault,SIGSEGV, SEGV_ACCERR,"level 2 permission fault"},
{ do_page_fault,SIGSEGV, SEGV_ACCERR,"level 3 permission fault"},
...
};
從代碼中可以看出:
出現(xiàn)0/1/2/3級頁表轉(zhuǎn)換錯誤時,會調(diào)用do_translation_fault,實際中do_translation_fault最終也會調(diào)用到do_page_fault;
出現(xiàn)1/2/3級頁表訪問權(quán)限的時候,會調(diào)用do_page_fault;
其他的錯誤則調(diào)用do_bad,其中未列出來的部分還包括do_sea等操作函數(shù);
do_translation_fault
do_page_fault
do_page_fault函數(shù)為頁錯誤異常處理的核心函數(shù),與體系結(jié)構(gòu)相關(guān),上圖中的handle_mm_fault函數(shù)為通用函數(shù),也就是不管哪種處理器結(jié)構(gòu),最終都會調(diào)用到該函數(shù)。
3. handle_mm_fault
handle_mm_fault用于處理用戶空間的頁錯誤異常:
進(jìn)程在用戶模式下訪問用戶虛擬地址,觸發(fā)頁錯誤異常;
進(jìn)程在內(nèi)核模式下訪問用戶虛擬地址,觸發(fā)頁錯誤異常;
從do_page_fault函數(shù)的流程圖中也能看出來,當(dāng)觸發(fā)異常的虛擬地址屬于某個vma,并且擁有觸發(fā)頁錯誤異常的權(quán)限時,會調(diào)用到handle_mm_fault函數(shù),而handle_mm_fault函數(shù)的主要邏輯是通過__handle_mm_fault來實現(xiàn)的。
流程如下圖:
3.1 do_fault
do_fault函數(shù)用于處理文件頁異常,包括以下三種情況:
讀文件頁錯誤;
寫私有文件頁錯誤;
寫共享文件頁錯誤;
3.2 do_anonymous_page
匿名頁的缺頁異常處理調(diào)用本函數(shù),在以下情況下會觸發(fā):
malloc/mmap分配了進(jìn)程地址空間區(qū)域,但是沒有進(jìn)行映射處理,在首次訪問時觸發(fā);
用戶棧不夠的情況下,進(jìn)行棧區(qū)的擴(kuò)大處理;
3.3 do_swap_page
如果訪問Swap頁面出錯(頁面不在內(nèi)存中),則從Swap cache或Swap文件中讀取該頁面。
由于在4.14內(nèi)核版本中,do_swap_page調(diào)用的很多函數(shù)都是空函數(shù),無法進(jìn)一步的了解,大體的流程如下圖:
3.4 do_wp_page
do_wp_page函數(shù)用于處理寫時復(fù)制(copy on write),會在以下兩種情況處理:
創(chuàng)建子進(jìn)程時,父子進(jìn)程會以只讀方式共享私有的匿名頁和文件頁,當(dāng)試圖寫的時候,觸發(fā)頁錯誤異常,從而復(fù)制物理頁,并創(chuàng)建映射;
進(jìn)程創(chuàng)建私有文件映射,讀訪問后觸發(fā)異常,將文件頁讀入到page cache中,并以只讀模式創(chuàng)建映射,之后發(fā)生寫訪問后,觸發(fā)COW;
關(guān)鍵的復(fù)制工作是由wp_page_copy完成的:
【原創(chuàng)】(十)Linux內(nèi)存管理 - zoned page frame allocator - 5
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本: ...
【原創(chuàng)】(六)Linux內(nèi)存管理 - zoned page frame allocator - 1
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本: ...
Linux內(nèi)存管理 (11)page引用計數(shù)
專題:Linux內(nèi)存管理專題 關(guān)鍵詞:struct page._count._mapcount.PG_locked/PG_referenced/PG_active/PG_dirty等. Linux的內(nèi) ...
【原創(chuàng)】(七)Linux內(nèi)存管理 - zoned page frame allocator - 2
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本: ...
【原創(chuàng)】(九)Linux內(nèi)存管理 - zoned page frame allocator - 4
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本: ...
【原創(chuàng)】(八)Linux內(nèi)存管理 - zoned page frame allocator - 3
背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本: ...
Linux內(nèi)存描述之內(nèi)存頁面page–Linux內(nèi)存管理(四)
服務(wù)器體系與共享存儲器架構(gòu) 日期 內(nèi)核版本 架構(gòu) 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...
伙伴系統(tǒng)之避免碎片--Linux內(nèi)存管理(十六)
1 前景提要 1.1 碎片化問題 分頁與分段 頁是信息的物理單位, 分頁是為了實現(xiàn)非連續(xù)分配, 以便解決內(nèi)存碎片問題, 或者說分頁是由于系統(tǒng)管理的需要. 段是信息的邏輯單位,它含有一組意義相對完整的信 ...
伙伴系統(tǒng)之伙伴系統(tǒng)概述--Linux內(nèi)存管理(十五)
在內(nèi)核初始化完成之后, 內(nèi)存管理的責(zé)任就由伙伴系統(tǒng)來承擔(dān). 伙伴系統(tǒng)基于一種相對簡單然而令人吃驚的強大算法. Linux內(nèi)核使用二進(jìn)制伙伴算法來管理和分配物理內(nèi)存頁面, 該算法由Knowlton設(shè)計, ...
隨機推薦
采用MVC模式JDBC演示案例
MVC三層架構(gòu): Model 模型層,數(shù)據(jù)處理和業(yè)務(wù)邏輯 View 視圖層,為客戶展示內(nèi)容 Control 控制層,協(xié)調(diào)控制,更新模型 案例如下: 1.獲得數(shù)據(jù)庫連接 package com.db; ...
【hihoCoder】1121:二分圖一·二分圖判定
題目 ??http://hihocoder.com/problemset/problem/1121 無向圖上有N個點,兩兩之間可以有連線,共有M條連線. 如果對所有點進(jìn)行涂色(白/黑),判定是否存 ...
javascript_basic_03之函數(shù)、循環(huán)、數(shù)組
1.函數(shù):函數(shù)(Function),方法(Method),過程(Procedure): 2.默認(rèn)為假的情況: ①if(0){}:②if(0.0){}:③if(null){}:④if("&qu ...
centos 軟件安裝 刪除
centos的軟件安裝大致可以分為兩種類型: [centos]rpm文件安裝,使用rpm指令? 類似[ubuntu]deb文件安裝,使用dpkg指令 [centos]yum安裝?? 類似[ubuntu ...
Android實現(xiàn)計時與倒計時(限時搶購)的幾種方法
在購物網(wǎng)站的促銷活動中一般都有倒計時限制購物時間或者折扣的時間,這些都是如何實現(xiàn)的呢? 在一個安卓客戶端項目中恰好遇到了類似的問題,一開始使用的是Timer與 TimerTask, 雖然此方法通用,但 ...
仿360新聞的熱搜圖片,win8風(fēng)格隨機九宮格布局
360新聞地址:http://sh.qihoo.com/i/ 感覺這效果挺好的,隨機九宮格,在不少地方可以用到,就研究了下他的源碼,基本原理就是預(yù)先定義好幾種布局模塊,然后根據(jù)需要進(jìn)行拼接,具體代碼可 ...
Netty實戰(zhàn)一之異步和事件驅(qū)動
Netty是一款異步的事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架,支持快速地開發(fā)可維護(hù)的高性能的面向協(xié)議的服務(wù)器和客戶端. 使用Netty你可以并不是很需要網(wǎng)絡(luò)編程.多線程處理.并發(fā)等專業(yè)Java知識的積蓄. Net ...
PHP加密與編碼技術(shù)
md5加密: string? md5( string $str [,bool $raw output=false]) md5加密方法用的挺多,有兩個參數(shù),第一個參數(shù)是要加密的字符串,第二個參數(shù)默認(rèn)為f ...
ttl傳輸中過期
上renren時遇到一問題,突然間就無法登陸,看了下網(wǎng)絡(luò),正常呀,別的網(wǎng)站完全ok,就這不成,所以就ping了一下做以校驗:如下圖示:傳輸中過期ttl,這問題少見,新鮮呀:趕緊查了查:原來可能是產(chǎn)生了 ...
WPF 每次只打開一個窗口
if(downListControl == null || downListControl.IsVisible == false) { downListControl = new DownloadLi ...
總結(jié)
以上是生活随笔為你收集整理的Linux内存page,【原创】(十四)Linux内存管理之page fault处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: red hat linux挂载u盘,请问
- 下一篇: linux剪贴板复制文件原理,linux