linux - 在概念上将用户虚拟地址、内核逻辑地址和内核虚拟地址捆绑在一起
问题描述
在查看了Linux x86 虚拟内存映射并阅读了内核虚拟地址和内核逻辑地址之间的差异(参见1、2、3、4、5等)之后,我有点困惑了。我创建了一个图表来帮助我解释并获得我所理解的反馈。(图表未按比例绘制,但虚拟内存地址来自 4 级 x86 内存映射)
首先,所有用户空间程序都处理用户空间虚拟地址。尽管用户空间地址空间共享相同的内核映射,但用户空间程序不能直接访问内核地址。所有用户空间虚拟地址都必须使用页表进行转换,如果内存在 RAM 中,则这会导致内存驻留在 RAM 上的物理地址。
其次,地址空间的内核部分(在 32 位系统中,是 3:1 的拆分,意味着 1 GB 用于内核),内核将地址空间的一部分用于逻辑地址。逻辑地址是直接映射到物理内存 (1:1) 的虚拟地址。
接下来,内核虚拟地址是驻留在内核地址空间区域内的任何地址,其中包括内核逻辑地址。因此,当人们问内核虚拟地址和内核逻辑地址之间有什么区别时,问题暗示它们是不同的,而实际上内核逻辑地址是内核虚拟地址的子集。他们真正要问的是内核逻辑虚拟地址和内核非逻辑虚拟地址之间的区别。由 使用的非逻辑虚拟地址vmalloc
是不直接映射到 RAM 甚至可能不映射到 RAM 的地址。
如果到目前为止我是正确的,那么以下两个结论是否正确?
映射的用户虚拟地址和内核非逻辑虚拟地址必须以完全相同的方式进行转换:通过遍历页表来获取物理地址。我的证据是function
vmalloc_to_page()
,因为它vmalloc
返回非逻辑虚拟地址。这意味着内核有自己的一组页表,这些页表不与任何用户空间进程相关联。在 x86-64 中,每个映射的用户虚拟地址或内核非逻辑虚拟地址都有一个对应的内核逻辑地址。例如,在我的图中,用户空间地址
0000700000000000
映射到0x1
. 因此,为了获得内核逻辑地址,我们添加到离开0x1
的直接映射基址。我们可以对具有物理地址的地址做同样的事情,它的内核逻辑地址是。这样,给定任何映射的非逻辑虚拟地址,内核至少有两个虚拟地址可用于查找物理地址(非逻辑虚拟地址及其等效的逻辑地址)。ffff888000000000
ffff888000000001
vmalloc
0x3
ffff888000000003
解决方案
推荐阅读
- python - 使用数据集 A 训练模型并使用数据集 B 进行测试
- c# - Unity 的 TMP_InputField 中可能出现故障,额外的不可见字符?
- javascript - 在循环中整合代码的更好方法是什么?
- db2 - 从声明游标锚定行数据类型变量
- swift - 如何使用扩展市场保存裁剪的 uiview 屏幕截图
- python - 子进程标准输出解码字符串不适用于希腊字母
- javers - 从不同实例保存相同的通用提交对象
- java - 我无法保存整数
- javascript - 使用单个正则表达式仅提取函数名称(字符串值)
- sql - 如果在 case 语句中为 null,则将日期时间转换为字符串“待定”