【內存管理】常用的頁表映射函數

1、pgd_addr_end

根據當前虛擬地址 addr 和目標結束地址 end,計算當前 PGD 項 能夠覆蓋的最大虛擬地址范圍的結束地址 next。

  • 如果 addr 和 end 跨越多個 PGD 項(即 end 超出當前 PGD 項的地址范圍),則返回當前 PGD 項的地址邊界。
  • 如果 end 在當前 PGD 項的地址范圍內,則返回 end。
  • 在建立頁表映射時,內核需要逐個處理每個 PGD 項對應的地址范圍。通過 pgd_addr_end,可以確定當前 PGD 項需要處理的地址范圍 [addr, next),并更新 addr 為 next,以便處理下一個 PGD 項。

頁表建立參考

do {next = pgd_addr_end(addr, end); // 計算當前 PGD 項的地址范圍alloc_init_pud(pgd, addr, next, phys, prot, alloc); // 初始化 PUD 頁表phys += next - addr; // 更新物理地址偏移
} while (pgd++, addr = next, addr != end);
  • 流程解釋:
    • 循環處理每個 PGD 項:通過 do-while 循環,逐個處理 PGD 項。
    • 計算當前 PGD 項的地址范圍:通過 pgd_addr_end 確定當前 PGD 項的地址范圍 [addr, next)。
    • 初始化下級頁表:調用 alloc_init_pud 為當前 PGD 項分配并初始化 PUD 頁表。
    • 更新物理地址偏移:根據當前處理的地址范圍大小(next - addr)調整物理地址 phys。
    • 移動到下一個 PGD 項:更新 addr 為 next,并繼續處理下一個 PGD 項,直到 addr == end。

2、pgd_offset_k

pgd_offset_k(addr) 是 Linux 內核中用于 獲取內核頁全局目錄(PGD)中對應虛擬地址 addr 的頁表項地址 的宏。它是內核頁表操作的核心宏之一,主要用于內核虛擬地址空間的映射初始化(如 early_fixmap_init)和頁表建立(如 create_mapping)等場景。


1. 宏的定義與展開

#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
  • init_mm:內核的全局內存描述符(mm_struct),表示內核的地址空間(與進程的 mm 分離)。
  • pgd_offset(mm, addr):根據 mm 的 PGD 基地址和 addr 計算對應的 PGD 項地址。

進一步展開:

#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
  • (mm)->pgd:內核 PGD 的基地址(init_mm.pgd)。
  • pgd_index(addr):從 addr 中提取 PGD 項的索引。

2. pgd_index(addr) 的計算

#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
  • PGDIR_SHIFT:定義 PGD 項的位移量,決定 PGD 項覆蓋的地址范圍。例如:
    • 對于 ARM64(4 級頁表),PGDIR_SHIFT = 39,每個 PGD 項覆蓋 2^(48-39) = 512GB 地址空間。
  • PTRS_PER_PGD:PGD 項的數量(通常為 1 << (PGDIR_SHIFT - VA_BITS_SHIFT),例如 512 項)。
  • 作用:通過右移 addr 并掩碼,提取 PGD 項的索引。

3. 典型使用場景

3.1 早期內核映射初始化(early_fixmap_init

在內核啟動階段,early_fixmap_init 函數會使用 pgd_offset_k 初始化固定映射區域(fixmap)的頁表:

pgd_t *pgd = pgd_offset_k(FIXADDR_START);
__pgd_populate(pgd, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
  • 作用:將 bm_pud(預分配的 PUD 頁表)的物理地址寫入 PGD 項中,建立從 FIXADDR_STARTbm_pud 的映射。
  • 后續步驟:通過 pud_offsetpmd_offsetpte_offset 逐級填充頁表。
3.2 通用頁表建立(create_mapping

在內核中,create_mapping 函數會通過 pgd_offset_k 遍歷虛擬地址范圍并建立頁表:

pgd_t *pgd = pgd_offset_k(virt_addr);
do {next = pgd_addr_end(addr, end);alloc_init_pud(pgd, addr, next, phys, prot);phys += next - addr;addr = next;
} while (pgd++, addr != end);
  • 作用:逐個處理每個 PGD 項的地址范圍,初始化下級頁表(PUD → PMD → PTE)。

4. ARM64 架構示例

假設:

  • addr = 0xffff7ffffabfe000FIXADDR_START
  • init_mm.pgd = 0xffff800000ef0000
  • PGDIR_SHIFT = 39PTRS_PER_PGD = 512
4.1 計算 pgd_index(addr)
pgd_index(addr) = (0xffff7ffffabfe000 >> 39) & 0x1ff = 0xff
  • 解釋addr 的高 9 位(0x1ff)即為 PGD 項的索引。
4.2 計算 pgd_offset_k(addr)
pgd_offset_k(addr) = init_mm.pgd + 0xff * sizeof(pgd_t)
  • ARM64 中 pgd_t 占 8 字節,因此:
    pgd_offset_k(addr) = 0xffff800000ef0000 + 0xff * 8 = 0xffff800000ef07f8
    
  • 結果:這是 addr 在內核 PGD 中對應項的虛擬地址。

5. 關鍵點總結

  1. 目的

    • 快速定位內核虛擬地址 addr 在 PGD 中的項地址。
    • 為后續頁表建立(如 PUDPMDPTE)提供起點。
  2. 層級關系

    • pgd_offset_k 屬于頁表操作宏的第一級(PGD),后續通過 pud_offsetpmd_offsetpte_offset 逐級展開。
  3. 架構依賴

    • PGDIR_SHIFTPTRS_PER_PGD 的定義依賴于架構(如 ARM64、x86)和頁表層級(4 級或 2 級)。
  4. 應用場景

    • 早期內核映射(fixmapioremap)。
    • 動態內存映射(vmallocioremap)。
    • 設備樹(DTB)的加載(通過 fixmap 映射物理地址)。

6. 常見問題

Q1:為什么 pgd_offset_k 使用 init_mm
  • 原因:內核地址空間是全局的,所有進程共享同一個內核 PGD(init_mm.pgd)。通過 init_mm 可直接訪問內核頁表。
Q2:如何驗證 pgd_offset_k 的正確性?
  • 調試方法:在 early_fixmap_init 中打印 pgd_offset_k(addr) 的值,并檢查其是否對應預期的 PGD 項地址(如通過 pr_err 輸出)。
Q3:ARM64 中為何需要乘以 8?
  • 原因:ARM64 的每個 PGD 項占用 8 字節(64 位),因此索引 0xff 對應的偏移量為 0xff * 8 = 0x7f8

7. 擴展:頁表層級劃分(以 ARM64 為例)

層級地址位移頁表項大小映射范圍
PGDpgd_index(addr)>> 398 字節512GB
PUDpud_index(addr)>> 308 字節1GB
PMDpmd_index(addr)>> 218 字節2MB
PTEpte_index(addr)>> 128 字節4KB

總結

pgd_offset_k(addr) 是內核頁表操作的基礎,通過計算虛擬地址 addr 在 PGD 中的項地址,為后續的頁表建立提供起點。理解其工作原理對于調試內核內存管理、分析頁表初始化流程至關重要。

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

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

相關文章

XR數字融合工作站賦能新能源汽車專業建設的創新路徑

XR數字融合工作站作為集PC、VR、MR技術于一體的軟硬件集成平臺&#xff0c;憑借其多維交互、虛實融合、智能管理等特性&#xff0c;為新能源汽車專業的教學改革與創新提供了全新解決方案。一、教學場景革新&#xff1a;構建沉浸式、互動化學習環境XR數字融合工作站通過多形態拼…

C語言通用鏈表終章:優雅的收尾 - 清空與銷毀

各類資料學習下載合集 ?https://pan.quark.cn/s/8c91ccb5a474? 經過前面的學習,我們已經從零構建了一個功能強大的通用鏈表,它能自如地進行節點的插入和刪除。我們的“數據火車”已經可以馳騁在內存的世界里。然而,旅途終有終點,當火車完成任務后,如何安全、徹底地讓…

MATLAB R2025a安裝配置及使用教程(超詳細保姆級教程)

文章目錄前言什么是MATLAB&#xff1f;了解這款數據分析利器matlab安裝前準備工作MATLAB R2025a下載完整MATLAB R2025a安裝步驟MATLAB進階應用技巧前言 全網最新最全的MATLAB R2025a安裝教程來了&#xff01;2025年版本完整圖文指南&#xff0c;包含軟件下載、詳細安裝、密鑰激…

在Mybatis plus中如何使用自定義Sql

在演示UpdateWrapper的案例中&#xff0c;我們在代碼中編寫了更新的SQL語句&#xff1a;Test void testUpadateWrapper(){List<Long> ids List.of(1L,2L,4L);//生成SQLUpadateWrapper<User> wrapper new UpdateWrapper<User> ().setSql("balance balan…

Deepoc科技之暖:智能助盲設備如何為視障家人點亮生活

作為一名視障人士的家屬&#xff0c;我們或許都經歷過這樣的時刻&#xff1a;看著親人在書架前摸索&#xff0c;卻無法獨自獲取文字信息&#xff1b;擔心他們外出時遇到障礙物或交通危險&#xff1b;心疼他們因找不到日常物品而不得不一次次求助。這些細微的日常困境&#xff0…

大模型食材識別技術革新:AI重構精準營養管理

隨著健康意識的提升&#xff0c;飲食管理需求激增&#xff0c;但傳統手動記錄易出錯、效率低。大模型食材識別技術的突破&#xff0c;讓AI通過多模態輸入精準識別食材種類與重量&#xff0c;結合營養數據庫&#xff0c;系統可快速生成營養報告&#xff0c;實現從“經驗驅動”到…

使用 Altair RapidMiner 將機器學習引入您的 Mendix 應用程序

Altair RapidMiner 使機器學習更加容易&#xff1a;無論您喜歡使用 Python 編碼&#xff0c;還是在 Workflow Studio 中進行可視化工作&#xff0c;Altair AI Cloud 都能為團隊提供快速構建和部署 ML 模型的工具。 將機器學習與 Mendix 集成很簡單&#xff1a;通過 Mendix 的低…

EasyExcel:快速讀寫Excel的工具類

EasyExcel&#xff1a;快速讀寫Excel的工具類 項目介紹 ?EasyExcel是一個基于Java的、快速、簡潔、解決大文件內存溢出的Excel處理工具。 他能讓你在不用考慮性能、內存的等因素的情況下&#xff0c;快速完成Excel的讀、寫等功能。 pom地址 ? <!--exel--> <depe…

WSL Ubuntu Docker 代理自動配置教程

WSL Ubuntu Docker 代理自動配置教程 WSL Ubuntu Docker 代理自動配置教程 背景說明 在 WSL2 環境下使用 Docker 時&#xff0c;由于網絡環境限制&#xff0c;經常需要通過 Windows 主機上的代理來訪問 Docker Hub。但每次 Windows 重啟后&#xff0c;WSL 獲取到的主機 IP 地址…

踩坑實錄:Django繼承AbstractUser時遇到的related_name沖突及解決方案

一、問題現象分析 咱們在用Django開發時&#xff0c;有時候需要擴展用戶模型&#xff0c;就會去繼承AbstractUser。但這么做的時候&#xff0c;要是沒處理好groups和user_permissions這兩個多對多字段的反向查詢名稱&#xff0c;就會遇到這樣的報錯&#xff1a;主要就是這種錯誤…

push pop 和 present dismiss

push/pop 和 present/dismiss 文章目錄push/pop 和 present/dismiss前言push / poppresent普通的present多層present多層present后的父子關系問題多層彈出會遇到的問題showViewController 和 showDetailViewControllershowViewControllershowDetailViewControllerdismiss模態化…

服務器異常負載排查手冊 · 隱蔽進程篇

適用范圍 適用于 Linux 3.10 生產環境&#xff0c;發現 load 高但用戶態 CPU 接近 0 % 的場景。1. 現場凍結目標&#xff1a;在 rootkit 干預前保存易失數據。#!/bin/bash # freeze.sh TS$(date %s) mkdir -p /srv/ir/${TS} cd /srv/ir/${TS}# 1.1 進程樹&#xff08;busybox 靜…

2024理想算法崗筆試筆記

要理解指令微調&#xff08;Instruction Tuning&#xff09;&#xff0c;需要先將其置于大語言模型&#xff08;LLM&#xff09;的訓練框架中 —— 它并非模型訓練的起點&#xff0c;而是針對 “讓模型更懂人類需求” 的關鍵優化步驟。簡單來說&#xff0c;指令微調是通過讓模型…

Oracle 11g離線安裝依賴包完整解決方案

本文還有配套的精品資源&#xff0c;點擊獲取 簡介&#xff1a;Oracle 11g是一款廣泛使用的關系型數據庫管理系統&#xff0c;在離線環境下安裝時需依賴多個系統庫和工具。本“oracle11g依賴包”壓縮文件包含了在CentOS 7.7上安裝Oracle 11g可能缺失的關鍵依賴RPM包&#xf…

VBA數據結構選型:效率差5倍的生死抉擇

VBA性能生死局&#xff1a;Dictionary與Collection效率差5倍&#xff01;90%開發者用反血虧“你以為Collection是VBA的‘輕量級選手’&#xff1f;大錯特錯&#xff01;實測數據顯示&#xff1a;在10萬級數據循環中&#xff0c;Dictionary的查詢速度比Collection快5倍&#xff…

電機控制(四)-級聯PID控制器與參數整定(MATLABSimulink)

PID算法 普通PID&#xff08;Proportional-Integral-Derivative&#xff09; 通過比例&#xff08;P&#xff09;、積分&#xff08;I&#xff09;和微分&#xff08;D&#xff09;三項來進行控制 比例項&#xff08;P&#xff09;&#xff1a;根據當前誤差&#xff08;目標值…

數據結構深度解析:二叉樹的基本原理

在數據結構體系中&#xff0c;樹是一種重要的非線性層次結構&#xff0c;它通過 “節點” 與 “邊” 的連接關系&#xff0c;模擬了現實世界中樹的分支結構&#xff0c;能夠高效地解決數據的查找、插入、刪除等問題。而二叉樹作為樹結構中最簡單、應用最廣泛的類型&#xff0c;…

【React】Ant Design 5.x 實現tabs圓角及反圓角效果

需要實現的效果實現思路 利用tab頁的before和after屬性&#xff0c;添加tab頁前后的圓弧屬性&#xff0c;同時使用tab頁的shadow陰影填充右下角的圓弧空缺部分。<TabsonChange{onChange}type"card"items{getTabItems()}/>.ant-tabs-nav{margin: 0;.ant-tabs-na…

WordPress過濾文章插入鏈接rel屬性noopener noreferrer值

WordPress過濾文章插入鏈接rel屬性noopener noreferrer值在保存文章的時候&#xff0c;WordPress會自動過濾文章內容中的鏈接&#xff0c;具有target屬性的鏈接會自動添加rel"noopener noreferrer"&#xff0c;該屬性是為了預防跨站攻擊&#xff0c;站內鏈接似乎沒有…

make_shared的使用

目錄 1. make_shared 的基本概念 基本用法 2. 引入 make_shared 的主要原因 2.1 解決傳統構造方式的問題 2.2 標準委員會的動機 3. make_shared 的核心優勢 3.1 性能優勢&#xff08;最重要優點&#xff09; 內存分配優化&#xff1a; 性能提升表現&#xff1a; 3.2 異…