Windows 虚拟地址 到底是如何映射到 物理地址 的?
一:背景
1. 讲故事
我发现有很多的 .NET程序员 写了很多年的代码都没弄清楚什么是 虚拟地址
,更不用谈什么是 物理地址
以及Windows是如何实现地址映射的了?这一篇我们就来聊一聊这两者之间的联系。
二:地址映射研究
1. 找虚拟地址
怎么去找 虚拟地址
呢?相信很多朋友都知道应用程序
用的是虚拟地址,所以从应用程序中取一个就好了,这里就拿 notepad 举例子吧。
开启一个装有 win10 的虚拟机,然后打开 notepad.exe,使用 windbg 进行它的内核态调式,参考代码如下:
0: kd> !process 0 0 notepad.exe
PROCESS ffffe0011f9c9840
SessionId: 1 Cid: 11a8 Peb: 7ff63d8ff000 ParentCid: 0bf4
DirBase: 23c6d000 ObjectTable: ffffc00088bdcbc0 HandleCount: <Data Not Accessible>
Image: notepad.exe
0: kd> .process /i /p ffffe0011f9c9840
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
0: kd> g
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPointWithStatus:
fffff801`bed59c50 cc int 3
1: kd> .reload /user
Loading User Symbols
....................................
Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long.
Run !sym noisy before .reload to track down problems loading symbols.
......
1: kd> lm
start end module name
00007ff6`3e1e0000 00007ff6`3e21a000 notepad (deferred)
00007ff9`83e60000 00007ff9`83fac000 UIAutomationCore (deferred)
...
1: kd> dB 00007ff6`3e1e0000+0x50 L30
00007ff6`3e1e0050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
00007ff6`3e1e0060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
00007ff6`3e1e0070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
从卦中可以看到 00007ff63e1e0050
处是一段字符串,接下来我们就以它为例吧。
2. 如何用 Windbg 推算
到底是如何映射的呢?如果你了解 Windows 的源码可能你就很清楚,不了解也没关系,我们可以用 WinDbg 帮我们计算,在 windbg 中有一个 !vtop
命令可以一键查找,输出如下:
1: kd> !vtop 0 00007ff63e1e0050
Amd64VtoP: Virt 00007ff63e1e0050, pagedir 0000000023c6d000
Amd64VtoP: PML4E 0000000023c6d7f8
Amd64VtoP: PDPE 000000002360aec0
Amd64VtoP: PDE 000000000b910f80
Amd64VtoP: PTE 000000001fa51f00
Amd64VtoP: Mapped phys 000000000ad38050
Virtual address 7ff63e1e0050 translates to physical address ad38050.
1: kd> !dB ad38050 L30
# ad38050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
# ad38060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
# ad38070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
从卦中可以清晰的看到,虚拟地址 00007ff63e1e0050
所对应的物理地址为 ad38050
,然后用 !dB
去观察物理地址也确实如此。
这里要提醒一下,如果你还想知道这个物理地址所属的 PDE (页目录项)
和 PTE (页表项)
,可以用 !pte
命令帮我们一键显示,输出如下:
1: kd> !pte 00007ff63e1e0050
VA 00007ff63e1e0050
PXE at FFFFF6FB7DBED7F8 PPE at FFFFF6FB7DAFFEC0 PDE at FFFFF6FB5FFD8F80 PTE at FFFFF6BFFB1F0F00
contains 009000002360A867 contains 00E000000B910867 contains 00F000001FA51867 contains 810000000AD38025
pfn 2360a ---DA--UWEV pfn b910 ---DA--UWEV pfn 1fa51 ---DA--UWEV pfn ad38 ----A--UR-V
从卦中可以看到,x64的地址有四级结构,不仅有 PDE,PTE
,还有 PXE, PPE
,并且从 pfn ad38
可以清楚的看到它的物理页号是 ad38
,加上虚拟地址后的 12bit(050) 偏移,最后的物理地址也就是 ad38050
。
用 WinDbg 推算虽然简单,但不利于我们了解原理,为了加深理解,我们需要手工的去推算。
3. 如何手工推算
要明白手工推算,在脑子中一定要有一张架构图,有了这张架构图就方便行事了。
卦图中有几点要解释。
- 二进制怎么出来的?
可以用 windbg 的 .formats 命令。
1: kd> .formats 00007ff63e1e0050
Evaluate expression:
Hex: 00007ff6`3e1e0050
Decimal: 140695580835920
Binary: 00000000 00000000 01111111 11110110 00111110 00011110 00000000 01010000
- CR3 是什么?
CR3 是Windows的控制寄存器,它记录着这个进程所属的虚拟地址首地址,专业点就是 BaseDir (基目录)
地址,参考如下输出:
1: kd> !process 0 0 notepad.exe
PROCESS ffffe0011f9c9840
SessionId: 1 Cid: 11a8 Peb: 7ff63d8ff000 ParentCid: 0bf4
DirBase: 23c6d000 ObjectTable: ffffc00088bdcbc0 HandleCount: <Data Not Accessible>
Image: notepad.exe
- 各级页表占用多少bit位数?
- PXE 占用 9bit(39-47)
- PPE 占用 9bit(30-38)
- PDE 占用 9bit(21-29)
- PTE 占用 9bit(12-20)
有了这些信息之后,最后就是手工推算了,这里要提醒一下,每个表的首地址都把后 12bit 抹为0,因为他们是表的meta信息,详细输出如下:
1: kd> !process 0 0 notepad.exe
PROCESS ffffe0011f9c9840
SessionId: 1 Cid: 11a8 Peb: 7ff63d8ff000 ParentCid: 0bf4
DirBase: 23c6d000 ObjectTable: ffffc00088bdcbc0 HandleCount: <Data Not Accessible>
Image: notepad.exe
1: kd> r cr3
cr3=0000000023c6d000
1: kd> !dp 23c6d000 + (0y011111111*8) L1
#23c6d7f8 00900000`2360a867
1: kd> !dp 2360a000+(0y111011000*8) L1
#2360aec0 00e00000`0b910867
1: kd> !dp 0b910000 + (0y111110000*8) L1
# b910f80 00f00000`1fa51867
1: kd> !dp 1fa51000+(0y111100000*8) L1
#1fa51f00 81000000`0ad38025
从卦中可以看到最后推算出来的是 810000000ad38025
,抹掉 高32bit
和 末 12bit
之后就变成了 ad38
,这个就是我们的 pfn (页帧号)
,如果你想核算一下 !dp 出来的值对不对,可以看下 !pte
命令中的 contains xxx
是不是这个值? 输出如下:
1: kd> !pte 00007ff63e1e0050
VA 00007ff63e1e0050
PXE at FFFFF6FB7DBED7F8 PPE at FFFFF6FB7DAFFEC0 PDE at FFFFF6FB5FFD8F80 PTE at FFFFF6BFFB1F0F00
contains 009000002360A867 contains 00E000000B910867 contains 00F000001FA51867 contains 810000000AD38025
pfn 2360a ---DA--UWEV pfn b910 ---DA--UWEV pfn 1fa51 ---DA--UWEV pfn ad38 ----A--UR-V
从卦中可以看到,四个地址和pfn都是对的,最后 pfn+页内偏移 = ad38050
,也就是我们苦苦寻找的 物理地址
,再次输出一下结果。
1: kd> !dB ad38050 L30
# ad38050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
# ad38060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
# ad38070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
三:总结
手工推算是不是非常的有意思,可以让我们更加的理解Windows底层玩法,WinDbg在手,天下我有!
Windows 虚拟地址 到底是如何映射到 物理地址 的?的更多相关文章
- 深入了解Windows句柄到底是什么
深入了解Windows句柄到底是什么 http://blog.csdn.net/wenzhou1219/article/details/17659485 总是有新入门的Windows程序员问我Wind ...
- 深入了解Windows句柄到底是什么(句柄是逻辑指针,或者是指向结构体的指针,图文并茂,非常清楚)good
总是有新入门的Windows程序员问我Windows的句柄到底是什么,我说你把它看做一种类似指针的标识就行了,但是显然这一答案不能让他们满意,然后我说去问问度娘吧,他们说不行网上的说法太多还难以理解. ...
- Windows虚拟地址转物理地址(原理+源码实现,附简单小工具)
...
- windows下操作linux虚拟机映射网络驱动器中文件提示chmod权限不足解决方案
为了方便操作,linux虚拟机会通过windows下连接网络驱动器的方式共享自己的文件,对于前端来说,我想把gulp放在windows磁盘,操作虚拟机中的php文件,一来节省虚拟机磁盘大小,二来解决虚 ...
- 学习windows编程 day4 之 自定义映射
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRU ...
- windows 中 到底是用的哪个java.exe??? 删除了PATH变量的Java设置还是可以运行java.exe windows/system32
到底是用的哪个java.exe??? 删除了PATH变量的Java设置还是可以运行java.exe JavaWindowsCC++C# 当电脑里面有多个jdk或是jre时,在cmd里面到底是用的哪个 ...
- 转:windows 下 netsh 实现 端口映射(端口转发)
本文转自:本文出自 “httpyuntianjxxll.spac..” 博客,请务必保留此出处http://333234.blog.51cto.com/323234/1135361 -----hapr ...
- Windows绘图中的GDI映射模式
对Windows编程新手来说,GDI编程中最困难的部分就是映射模式(Mapping Mode). 什么是映射模式? 我们知道,GDI画图是在设备描述表这个逻辑意义上的显示平面上进行,其使用的是逻辑坐标 ...
- Windows自带NAT端口映射,命令行CMD操作即可
由于有需求进行端口映射,又不想装乱七八糟的软件,Windows本身自带的路由远程访问配置太麻烦,还要两块网卡,坑爹啊. 其实Windows本身命令行支持配置端口映射,条件是已经安装了IPV6,启不启用 ...
- windows中将网络共享文件夹映射为网络硬盘
目的是: 实现局域网,不同电脑之间共享文件. 例如: 计划将A电脑 的文件夹C:\MM ,共享给局域网电脑 B. 局域网所有电脑都可访问: 1. 在A电脑中 共享文件夹..选择‘启用网络发现’ ‘ ...
随机推荐
- Django4全栈进阶之路20 项目实战(三种方式开发部门管理):方式一:FBV
1.模型 from django.db import models from django.contrib.auth.models import User # Create your models h ...
- Python对两个Excel操作
简介 现在有个需求,我们根据需要 data.xlsx 中某些单元格的内容来查找 find.xlsx 中的某些內容. 数据内容(为了数据安全,所有数据均已模糊处理) data.xlsx内容: find. ...
- pbootcms对接微信扫码登录代码核心片段和步骤(前后端)
首先需要在微信公众平台或开放平台中创建应用,并获取到AppID和AppSecret. 在pbootcms中创建一个自定义模板页面(例如:wechat_login.html),并在该页面中添加以下代码, ...
- 把vue组件发布到npm
一直以来项目都使用他人开发的组件,于是乎自己也想倒腾着做一个,发布到npm 在其他项目里直接使用,这个组件上传和纯js 还是有一定区别的,在这个过程中也遇到了一些小问题,网上找了许多案例,都不是太全面 ...
- SVM主体思路和代码实现
之前学习的KNN算法属于直接将所有的训练图片数据化,根据图片的像素值进行判断,最简单的NN算法是用与待判断图片的差距最小(距离最近)的那张图片的类别当做此图片的类别,我们不难看到,1NN算法的正确性很 ...
- 一步步教你如何搭建K8S集群
一.环境配置 三台CentOS7虚拟机,默认配置,内存2GB.处理器2核心. 先更新下系统 1 sudo yum update 2 sudo yum upgrade 二.安装并启动 docker 1 ...
- ChatGPT玩法(二):AI玩转Excel表格处理
前言 在线免费体验ChatGpt:https://www.topgpt.one 你是否还在为记不住Excel的繁琐函数和公式而苦恼?如果是这样,那么不妨试试ChatExcel.即使你对函数一窍不通,也 ...
- 【Python】sqlmodel: Python 数据库管理ORM 的终极形态?
ORM 大家都知道ORM(Object Relational Mapping)是一种将对象和关系数据库中的表进行映射的技术,它可以让开发者更加方便地操作数据库,而不用直接使用SQL语句. 直接使用SQ ...
- 【Netty实战】1~3章学习笔记
1. Netty总体结构 1.1 Netty简介 Netty是一款用于创建高性能网络应用程序的高级框架.它的基于 Java NIO 的异步的和事件驱动的实现,保证了高负载下应用程序性能的最大化和可 ...
- 【Oracle】使用PL/SQL实现冒泡排序
[Oracle]使用PL/SQL实现冒泡排序 一般来说,SQL要排序的话直接使用order by即可 不一般来说,就是瞎搞,正好也可以巩固自己的数据结构基础 存储包内容如下 规范: create or ...