当前位置: 首页 > news >正文

linux内核 虚拟地址空间如何组织

核心比喻 把虚拟地址空间想象成一栋超高层大楼的房间编号系统。 每个进程都有自己的一份"房间号码本"(页表),同样的房间号在不同进程的号码本里指向不同的实际物理房间。内核就像大楼的物业 ,住在每栋楼的顶层,所有楼共用同一个物业办公室。 --- 地址空间布局 x86_64 进程虚拟地址空间(简化) 高地址 0xFFFFFFFFFFFFFFFF ┌─────────────────────────────┐ │ │ │ 内核空间 │ ← 所有进程共享同一份内核 │(128TB)│ 用户态无法直接访问 │ │ ├─────────────────────────────┤ ← 0xFFFF800000000000 │ │ │ 不可用空洞 │ ← x86_64 地址空间空洞 │ │ ├─────────────────────────────┤ ← 0x00007FFFFFFFFFFF │ 栈(Stack)│ ← 向下增长,局部变量、函数调用 │ ↓ │ │ │ │ 内存映射区 │ ← mmap、动态库加载在这里 │ ↓ │ │ │ │ 堆(Heap)│ ← malloc 从这里分配,向上增长 │ ↑ │ ├─────────────────────────────┤ │ BSS 段 │ ← 未初始化全局变量 │ 数据段 │ ← 已初始化全局变量 │ 代码段 │ ← 程序指令(只读) │ │ 低地址 0x0000000000000000 --- PHP 模拟示例 用 PHP 模拟"两个进程各自的虚拟地址空间"以及页表映射关系:<?php //============================================================// 模拟物理内存:就是一块真实存在的内存数组 // 下标=物理页帧号(PFN),值=实际存储的数据 //============================================================$physicalMemory=[0=>'[物理页0] 进程A的代码',1=>'[物理页1] 进程B的代码',2=>'[物理页2] 进程A的全局变量 x=100',3=>'[物理页3] 进程B的全局变量 x=999',4=>'[物理页4] 内核代码(所有进程共享)',5=>'[物理页5] 进程A的堆数据',6=>'[物理页6] 进程B的堆数据',];//============================================================// 页表:虚拟页号=>物理页帧号 // 每个进程有自己独立的页表(就是 CR3 寄存器指向的那张表) //============================================================$pageTableA=[// 虚拟页号=>物理页帧号 0x1000=>0, // 进程A 代码段 ->物理页0 0x2000=>2, // 进程A 数据段 ->物理页2 0x3000=>5, // 进程A 堆 ->物理页5 0xF000=>4, // 内核空间 ->物理页4(共享)];$pageTableB=[// 同样的虚拟地址,映射到不同物理页! 0x1000=>1, // 进程B 代码段 ->物理页1 0x2000=>3, // 进程B 数据段 ->物理页3 0x3000=>6, // 进程B 堆 ->物理页6 0xF000=>4, // 内核空间 ->物理页4(共享,和A一样)];//============================================================// MMU 地址翻译:虚拟地址 ->物理地址 // 真实硬件由 CPU 的 MMU 完成,这里用函数模拟 //============================================================functiontranslateAddress(int$virtualAddr, array$pageTable, array$physicalMemory): string{// 取虚拟页号(简化:直接用地址作为页号)$vpn=$virtualAddr;if(!isset($pageTable[$vpn])){// 页表里没有 ->触发缺页异常(Page Fault)return"缺页异常!虚拟地址 0x".dechex($virtualAddr)." 未映射,内核介入处理";}$pfn=$pageTable[$vpn];// 物理页帧号return$physicalMemory[$pfn];}//============================================================// 模拟两个进程访问"相同虚拟地址"//============================================================echo"=== 进程 A 访问虚拟地址 0x1000(代码段)===\n";echotranslateAddress(0x1000,$pageTableA,$physicalMemory)."\n\n";echo"=== 进程 B 访问虚拟地址 0x1000(代码段)===\n";echotranslateAddress(0x1000,$pageTableB,$physicalMemory)."\n\n";echo"=== 关键:相同虚拟地址,不同物理内存!===\n";echo"进程A 0x1000 -> 物理页 ".$pageTableA[0x1000]."\n";echo"进程B 0x1000 -> 物理页 ".$pageTableB[0x1000]."\n\n";echo"=== 两个进程访问内核空间(共享)===\n";echo"进程A 内核: ".translateAddress(0xF000,$pageTableA,$physicalMemory)."\n";echo"进程B 内核: ".translateAddress(0xF000,$pageTableB,$physicalMemory)."\n\n";echo"=== 访问未映射地址(触发缺页)===\n";echotranslateAddress(0x9999,$pageTableA,$physicalMemory)."\n";输出结果:===进程 A 访问虚拟地址 0x1000(代码段)===[物理页0]进程A的代码===进程 B 访问虚拟地址 0x1000(代码段)===[物理页1]进程B的代码===关键:相同虚拟地址,不同物理内存!===进程A 0x1000 ->物理页0进程B 0x1000 ->物理页1===两个进程访问内核空间(共享)===进程A 内核:[物理页4]内核代码(所有进程共享) 进程B 内核:[物理页4]内核代码(所有进程共享)===访问未映射地址(触发缺页)===缺页异常!虚拟地址 0x9999 未映射,内核介入处理 --- 进程切换时发生了什么<?php //============================================================// 模拟 CPU 的 CR3 寄存器(存放当前进程页表的物理地址) // 进程切换=换一张页表=修改 CR3 //============================================================class CPU{// CR3 寄存器:指向当前进程的页表 private array$cr3=[];private string$currentProcess='';publicfunctioncontextSwitch(string$processName, array$pageTable): void{echo">>> 上下文切换:{$this->currentProcess} -> {$processName}\n";echo" CR3 寄存器更新为 {$processName} 的页表\n";echo" TLB 全部刷新(旧的地址翻译缓存失效)\n\n";$this->cr3=$pageTable;$this->currentProcess=$processName;}publicfunctionaccessMemory(int$virtualAddr, array$physicalMemory): string{if(!isset($this->cr3[$virtualAddr])){return"缺页异常";}$pfn=$this->cr3[$virtualAddr];return"[{$this->currentProcess}] 读到: ".$physicalMemory[$pfn];}}$physicalMemory=[0=>'进程A的数据',1=>'进程B的数据',];$pageTableA=[0x2000=>0];$pageTableB=[0x2000=>1];$cpu=new CPU();// 调度器让进程A运行$cpu->contextSwitch('进程A',$pageTableA);echo$cpu->accessMemory(0x2000,$physicalMemory)."\n\n";// 调度器切换到进程B$cpu->contextSwitch('进程B',$pageTableB);echo$cpu->accessMemory(0x2000,$physicalMemory)."\n";输出:>>>上下文切换: ->进程A CR3 寄存器更新为 进程A 的页表 TLB 全部刷新(旧的地址翻译缓存失效)[进程A]读到: 进程A的数据>>>上下文切换:进程A ->进程B CR3 寄存器更新为 进程B 的页表 TLB 全部刷新(旧的地址翻译缓存失效)[进程B]读到: 进程B的数据 --- 一句话总结 ┌──────────────┬──────────────────────────────────────────────┐ │ 概念 │ 大白话 │ ├──────────────┼──────────────────────────────────────────────┤ │ 虚拟地址 │ 进程以为自己用的地址,是假的 │ ├──────────────┼──────────────────────────────────────────────┤ │ 物理地址 │ 内存条上真实的位置 │ ├──────────────┼──────────────────────────────────────────────┤ │ 页表 │ 虚拟地址到物理地址的翻译字典 │ ├──────────────┼──────────────────────────────────────────────┤ │ CR3寄存器 │ CPU当前用哪本字典 │ ├──────────────┼──────────────────────────────────────────────┤ │ 进程切换 │ 换一本字典,同一个地址翻出不同结果 │ ├──────────────┼──────────────────────────────────────────────┤ │ 缺页异常 │ 字典里查不到,内核来补页 │ ├──────────────┼──────────────────────────────────────────────┤ │ 内核空间共享 │ 所有进程的字典里,内核那页指向同一个物理位置 │
http://www.jsqmd.com/news/753018/

相关文章:

  • 在Node.js后端服务中集成Taotoken实现多轮对话与流式响应
  • 如何利用Taotoken CLI工具一键配置团队开发环境
  • 小型企业项目选型 ThinkPHP 还是 Symfony 哪个上手更快?
  • 赋能个体创业,购在数网打造三网话费增值服务新标杆 - 博客湾
  • 使用 Python 快速开始你的第一个 Taotoken 大模型调用
  • 如何快速掌握ComfyUI Manager插件管理:从新手到专家的完整指南
  • 【限时解禁】.NET 9边缘调试符号服务器私有部署手册(含Azure Sphere兼容性验证报告及SHA256校验码)
  • tfstk cookie逆向
  • 如何轻松实现单机游戏本地分屏:Nucleus Co-Op完整使用指南
  • 5分钟极速上手:BLiveChat让B站弹幕在OBS中优雅展示的完整指南
  • 外部只读诊断工具triage:AI Agent网关故障排查的独立法医
  • 政策利好加持,购在数网抢占电信增值服务蓝海市场 - 博客湾
  • 全志T153开发板 USB触摸屏驱动移植指南
  • 用CUDA加速FFT?保姆级教程:从MATLAB数据准备到CUFFT结果验证(含完整代码)
  • 【最后一批可免费获取】Zend Engine 4.9 JIT调试符号包+自研jit-trace-analyzer工具链(仅支持PHP 8.9.0–8.9.4,7天后关闭下载)
  • 通过 OpenClaw 的 CLI 子命令快速写入 Taotoken 配置
  • 手机变身高精度测绘仪:RtkGps如何让Android设备实现厘米级定位突破
  • 2026冷却塔除垢公司权威推荐:专业服务商选型指南 实力品牌测评出炉 - 博客湾
  • 普惠创业赋能,购在数网助力普通人实现创业梦想 - 博客湾
  • K8S集群的搭建
  • 3分钟上手Scrcpy Mask:用键盘鼠标玩转安卓设备的终极指南
  • 当ML.NET Pipeline在.NET 9中静默失败——3类不可捕获AI异常的内存快照取证技术(含WinDbg+PerfView双工具链脚本)
  • 把信任关进安全边界里,聊透 SAP 系统里的密钥保护
  • 【.NET 9 AI推理本地化实战指南】:零GPU依赖、30分钟完成Llama-3/Phi-4离线部署
  • CCF GESP C++ 一级上机题完整分类汇总
  • 手把手教你理解LIN总线的‘显性’与‘隐性’:从电平逻辑到汽车抗干扰的实战解析
  • OpenClaw 2026.3.8 更新了哪些内容?备份 CLI、Talk 静默超时、TUI Agent 识别与 ACP 溯源能力解析
  • 安装yolo26【无标题】
  • 超越频谱分析:双谱图在机械故障诊断中的实战应用指南(以Python为例)
  • 数据库Skill开发教程:从零构建SQLite应用