Linux內核源碼詳解--缺頁異常(Page Fault)處理的核心函數handle_pte_fault

handle_pte_fault 是 Linux 內核中處理缺頁異常(Page Fault)的核心函數,負責根據頁表項(PTE)的狀態和訪問權限,分發到不同的子處理邏輯(如匿名頁映射、文件頁映射、寫時復制、NUMA 遷移等)。以下基于代碼邏輯和搜索結果詳細解析其功能、原理及處理流程。

?

一、功能概述

?

handle_pte_fault 在缺頁異常處理流程中被調用(通常由 __handle_mm_fault 觸發),用于處理以下場景:

?

?1.首次訪問未映射的虛擬地址(PTE 為空)。

?

?2.訪問已被換出(Swap Out)的頁面(PTE 存在但 PRESENT 位為 0)。

?

?3.寫保護觸發寫時復制(COW)。

?

?4.NUMA 內存頁遷移優化。

?

?5.權限檢查與頁表狀態更新。

?

二、代碼邏輯分步解析

?

1. 檢查 PMD 狀態(大頁/透明大頁處理)

?

if (unlikely(pmd_none(*vmf->pmd))) {

? ? vmf->pte = NULL; // 延遲 PTE 分配,避免與透明大頁沖突

} else if (pmd_devmap_trans_unstable(vmf->pmd)) {

? ? return 0; // 透明大頁不穩定狀態,需重試

} else {

? ? vmf->pte = pte_offset_map(vmf->pmd, vmf->address); // 獲取 PTE

? ? vmf->orig_pte = *vmf->pte;

? ? barrier();

? ? if (pte_none(vmf->orig_pte)) { // PTE 為空則解除映射

? ? ? ? pte_unmap(vmf->pte);

? ? ? ? vmf->pte = NULL;

? ? }

}

?

關鍵點:

?

?若 PMD 未分配(pmd_none),暫不分配 PTE,避免干擾透明大頁(THP)的并發操作。

?

?pmd_devmap_trans_unstable 處理透明大頁分裂場景。

?

?

2. 處理 PTE 為空的情況(首次映射)?

?

if (!vmf->pte) {

? ? if (vma_is_anonymous(vmf->vma))

? ? ? ? return do_anonymous_page(vmf); // 匿名頁映射

? ? else

? ? ? ? return do_fault(vmf); // 文件頁/共享內存映射

}

?

static inline bool vma_is_anonymous(struct vm_area_struct *vma)

{

?return !vma->vm_ops;

}

?

分發邏輯:

?

?匿名頁(vma->vm_ops == NULL):

?

? 讀操作:映射到零頁(Zero Page)以減少物理內存占用。

?

? 寫操作:分配新物理頁并初始化。

?

?文件頁(vma->vm_ops != NULL):

?

? 觸發文件系統缺頁處理(如 filemap_fault),從磁盤讀取數據到 Page Cache

?

3. 處理 PTE 存在但 PRESENT 位為 0(已換出)

?

if (!pte_present(vmf->orig_pte))

? ? return do_swap_page(vmf); // 換回(Swap In)頁面

?

原理:

PTE 存儲了 Swap Entry(標識磁盤位置),需調用 do_swap_page 將數據從 Swap 分區讀回物理內存

?

?

4. 處理 NUMA 遷移優化

?

if (pte_protnone(vmf->orig_pte) && vma_is_accessible(vmf->vma))

? ? return do_numa_page(vmf); // 遷移頁面到當前 NUMA 節點

?

場景:

?

當物理頁位于遠端 NUMA 節點時,遷移以提升訪問性能。

?

5. 寫操作與寫時復制(COW)

?

if (vmf->flags & FAULT_FLAG_WRITE) {

? ? if (!pte_write(entry))

? ? ? ? return do_wp_page(vmf); // 觸發寫時復制

? ? entry = pte_mkdirty(entry); // 標記臟頁

}

?

COW 機制:

?

寫只讀頁時,分配新物理頁并復制內容,更新 PTE 指向新頁(原頁引用計數減 1)

?

若物理頁僅被一個進程引用(無共享),則直接設為可寫,避免復制。?

?

6. 更新 PTE 與 TLB 刷新

?

entry = pte_mkyoung(entry); // 標記訪問位(PTE_AF)

if (ptep_set_access_flags(vma, address, pte, entry, write)) {

? ? update_mmu_cache(vma, address, pte); // 更新 CPU 緩存

} else if (write) {

? ? flush_tlb_fix_spurious_fault(vma, address); // 刷新 TLB 偽錯誤

}

?

關鍵操作:

?

ptep_set_access_flags:原子更新 PTE 的訪問/臟位。

?

TLB 刷新僅在權限變更時觸發(避免冗余刷新提升性能)。

?

?

三、處理流程圖解

?

graph TD

? ? A[handle_pte_fault] --> B{PMD 有效?}

? ? B -- Yes --> C[獲取 PTE]

? ? B -- No --> D[延遲 PTE 分配]

? ? C --> E{PTE 為空?}

? ? E -- Yes --> F{匿名頁?}

? ? F -- Yes --> G[do_anonymous_page]

? ? F -- No --> H[do_fault]

? ? E -- No --> I{PTE Present?}

? ? I -- No --> J[do_swap_page]

? ? I -- Yes --> K{NUMA 遷移?}

? ? K -- Yes --> L[do_numa_page]

? ? K -- No --> M{寫操作且只讀?}

? ? M -- Yes --> N[do_wp_page]

? ? M -- No --> O[更新 PTE 標志]

? ? O --> P[刷新 TLB/緩存]

?

四、關鍵設計思想

?

延遲與優化:

?

?延遲 PTE 分配以避免透明大頁沖突。

?

?零頁映射節省匿名頁首次讀的內存

?

?

分層處理:

?

?按 PTE 狀態(空/換出/寫保護)分發給專用子函數,確保邏輯清晰。

?

并發控制:

?

?通過 spin_lock(vmf->ptl) 鎖定頁表,防止并行修改

?

性能優化:

?

?減少 TLB 刷新(僅在權限變更時觸發)。

?

?區分 major/minor fault(是否涉及磁盤 I/O)?

?

五、典型場景與子函數對照表

?

場景 觸發條件 處理函數 說明

?

匿名頁首次訪問 vmf->pte == NULL & 匿名 VMA do_anonymous_page 讀:零頁;寫:分配新頁

?

文件頁首次映射 vmf->pte == NULL & 文件 VMA do_fault 讀文件到 Page Cache

?

頁面已換出 !pte_present(entry) do_swap_page 從 Swap 分區讀回數據

?

寫只讀頁(COW) write & !pte_write(entry) do_wp_page 復制頁面或直接設可寫

?

NUMA 優化遷移 pte_protnone(entry) do_numa_page 遷移頁面至本地 NUMA 節點

?

頁表更新 權限變更(如臟頁/訪問位) ptep_set_access_flags 更新 PTE 并刷新 TLB?

?

?

六、總結

?

handle_pte_fault 是 Linux 虛擬內存管理的核心樞紐,通過狀態機式的分發邏輯處理各類缺頁異常:

?

匿名/文件頁:按需分配物理頁或讀取文件數據。

?

COW 機制:平衡內存共享與寫操作性能。

?

Swap 與 NUMA:優化內存不足和跨節點訪問場景。

其設計充分體現了 “懶加載”(Lazy Allocation)和 “最小化開銷”(如零頁、延遲刷新 TLB)的原則,確保高效管理復雜的內存訪問需求。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93825.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93825.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93825.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于混合注意力網絡和深度信念網絡的魯棒視頻水印技術基礎理論深度解析

1. 引言隨著數字媒體技術的迅猛發展和互聯網的普及,視頻內容的創作、傳播和分享變得前所未有的便捷。然而,這種便利性也帶來了嚴重的版權保護挑戰。數字視頻的易復制性使得盜版和非法傳播成為困擾內容創作者和版權所有者的重大問題。傳統的加密技術雖然能…

linux 之virtio 的驅動框架

1、基本知識 上一篇文章介紹了 virtio 的核心數據的實現和邏輯:linux 之 virtio 子系統核心的數據結構-CSDN博客 virtio 是對半虛擬化 hypervisor 中的一組通用模擬設備的抽象。它允許 hypervisor 導出一組通用的模擬設備,并通過一個通用的應用編程接口…

項目1總結其三(圖片上傳功能)

1、UploadService public interface UploadService {//上傳圖片String uploadImage(MultipartFile file, String type); }upload.location D:/upload Value("${upload.location}")private String uploadLocation;//文件上傳路徑Overridepublic String uploadImage(M…

Linux應用層開發--線程池介紹

Glib 線程池 1. 線程池簡介 線程池是一種管理和重用多個線程的設計模式: 避免頻繁創建/銷毀線程的開銷。提高性能與資源利用率。任務提交后,由線程池內的線程自動執行,任務執行完線程不會退出,而是繼續等待下一個任務。 2. Gli…

【Python】Python 多進程與多線程:從原理到實踐

Python 多進程與多線程:從原理到實踐 文章目錄Python 多進程與多線程:從原理到實踐前言一、并發編程基礎:進程與線程1.1 進程(Process)1.2 線程(Thread)1.3 進程與線程的關系二、Python 中的 &q…

electron-vite_18Less和Sass共用樣式指定

項目中可以封裝less公用樣式和方法&#xff0c;比如自動以滾動條樣式、單行省略號、多行省略號、display:none等&#xff1b;關于additionalData的配置生效,請在main.js中引入一個別的樣式或vue組件中使用“<style lang“scss”><style>”找到electron.vite.config…

Python面試題及詳細答案150道(71-80) -- 文件操作篇

《前后端面試題》專欄集合了前后端各個知識模塊的面試題&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

python新工具-uv包管理工具

uv 是一個由 Astral (Ruff 的創建者) 開發的極速 Python 包和項目管理器&#xff0c;用 Rust 編寫。它旨在作為傳統 Python 包管理工具&#xff08;如 pip、pip-tools、pipx、poetry、pyenv、twine 和 virtualenv 等&#xff09;的替代品&#xff0c;通過其高性能和多功能集成&…

有關spring-ai的defaultSystem與systemMessage優先級

今天在寫項目的時候想用nacos隨時修改system的prompt&#xff0c;突然發現defaultSystem的優先級比systemMessage高很多&#xff0c;廢話我就不說了&#xff0c;看圖吧。你覺得證據不夠&#xff1f;那這樣呢&#xff1f;

#運維 | 前端 # Linux http.server 實踐:隱藏長文件名,簡短路徑 (http://IP:port/別名 ) 訪問

如何運行頁面為 http://ip:port/名稱 1. 準備文件目錄 假設文件原始位置&#xff1a; /home/ubuntu/projects/yinran/ckd.html將它移動到子目錄并改名為 index.html&#xff1a; mkdir -p /home/ubuntu/projects/yinran/ckd mv /home/ubuntu/projects/yinran/ckd.html \/home/u…

任務管理器不刷新

記錄一個小問題&#xff1a; 進入任務管理器之后發現頁面不會刷新&#xff0c;性能界面也是一致。解決辦法&#xff1a;查看–>更新速度–>正常

2025-08-21 Python進階9——__main__與lambda

文章目錄1 \_\_main\_\_1.1 name 變量1.1.1 當模塊作為主程序直接運行時1.1.2 當模塊被其他模塊導入時1.2 \_\_main\_\_ 的含義1.3 if \_\_name\_\_ \_\_main\_\_1.5 小結2 lambda表達式2.1 基本概念2.2 lambda 函數語法2.3 使用示例2.4 與高階函數結合使用2.4.1 與 map () 結…

Java:將視頻上傳到騰訊云并通過騰訊云點播播放

功能需求:傳入一個videoFile也就是視頻字節流,返回騰訊云點播的視頻保存url需要在騰訊云中尋找的配置信息:導入的依賴:<!--騰訊云點播--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId&…

Unity3D物理游戲網絡同步指南

前言 Unity3D 物理游戲的網絡同步是一個復雜但非常核心的話題。要實現一個流暢、公平且可擴展的多人物理游戲&#xff0c;需要深入的理解和精心的設計。 下面我將為你全面解析 Unity3D 物理游戲的網絡同步&#xff0c;包括核心概念、主流方案、實現細節以及最佳實踐。 對惹&…

Amazon Redshift 訪問配置完整指南

概述 Amazon Redshift 是 AWS 提供的云端數據倉庫服務,支持多種訪問方式。本文將詳細介紹如何配置 IAM 權限、使用 AWS 控制臺 Query Editor v2,以及通過 SQL Workbench/J 等第三方工具連接 Redshift 集群。 目錄 環境準備 IAM 權限配置 Redshift 用戶管理 AWS 控制臺訪問 …

electron-vite_19配置環境變量

前端配罟環境變量主要通過項目根目錄下的.env系列文件實現&#xff0c;不同框架(如Vue、React)或構建工具(如Vite、Webpack)的具體操作略有差異&#xff0c;但核心邏輯均為通過環境變量文件區分開發、測試、生產等環境。方案1: 直接在根目錄新建.env文件 1.在根目錄新建 .env.d…

【python】arange用法

1. NumPy 里的 np.arangeimport numpy as np# 語法 np.arange([start, ]stop, [step, ], dtypeNone)參數說明&#xff1a;start&#xff1a;起始值&#xff08;默認 0&#xff09;stop&#xff1a;終止值&#xff08;不包含這個值&#xff09;step&#xff1a;步長&#xff08;…

力扣1005:k次取反后最大化的數組和

力扣1005:k次取反后最大化的數組和題目思路代碼題目 給你一個整數數組 nums 和一個整數 k &#xff0c;按以下方法修改該數組&#xff1a; 選擇某個下標 i 并將 nums[i] 替換為 -nums[i] 。 重復這個過程恰好 k 次。可以多次選擇同一個下標 i 。 以這種方式修改數組后&…

國產數據庫管理工具 CloudDM 2.7.1.0 發布,OceanBase 等數據源支持復雜 SQL 脫敏數據

CloudDM 是 ClouGence 公司推出的面向團隊使用的數據庫管理工具&#xff0c;支持云上、云下、多云等多種環境&#xff0c;并且提供多達 23 種數據源的支持。CloudDM 還支持數據庫 DevOps CI/CD 功能&#xff0c;將用戶產品發布流程中數據庫發布和程序發布無縫串聯起來。 更新亮…

AI大模型實戰:用自然語言處理技術高效處理日常瑣事

引言在數字化時代&#xff0c;我們每天都會面對大量的瑣碎事務&#xff1a;整理會議記錄、處理名單數據、撰寫學習筆記等等。這些工作不僅耗時&#xff0c;而且容易出錯。幸運的是&#xff0c;隨著人工智能技術的發展&#xff0c;特別是大語言模型&#xff08;LLM&#xff09;的…