一篇就让你了解进程的虚拟地址与物理地址是如何进行映射的
这篇文章可以让你了解进程的虚拟地址是如何映射物理地址的,在刚开始接触虚拟地址的概念时,真的是一头雾水,不知道它到底是个什么东西,一直有这个疑惑,为什么要用虚拟地址,虚拟地址的作用是什么?
经过这么多年做过的项目,积攒经验后,我可以略知一些虚拟地址的作用:
1. 代码的移植性变得更加的好,在不同的平台进行编译后,就可以直接运行,因为代码和虚拟地址打交道,到别的系统上,都会将你的虚拟地址转换为物理地址,如果不用虚拟地址,用物理地址,那么到了别的平台,就得考虑代码当前使用的物理地址,是否被别人使用了。
2. 不需要考虑内存分配的问题,也不需要担心内存不足,两个程序抢同一块内存导致崩溃的情况。
3. 还有一个好处就是,虚拟地址映射的不一定是物理地址,还可能是硬盘上的某一块地方,比如,把暂时不用的数据放到硬盘的虚拟内存上。
既然,虚拟内存是虚拟的,那么必然有一块实际的内存与它做映射才可以使用,那么,虚拟地址和物理地址是如何做映射的呢,下面,就给大家讲讲。
提到虚拟地址和物理地址的映射,不得不说一下在它俩之间其实还有一个线性地址的存在,那么进程想要访问真正的物理地址,首先要将虚拟地址转换为线性地址,然后经过MMU就可以将线性地址转换为真正的物理地址。
虚拟地址到物理地址转换的逻辑图
下面一步一步来进行讲解,先讲讲虚拟地址和线性地址是如何进行转换的吧:
转换过程中,就需要一个寄存器,那就是段寄存器,段寄存器中存储的是描述符表的索引,你可以把描述符表看成是一个数组,那么段寄存器中的索引,你可以当成是数组的下标,这下你明白了吧。
上面说的描述符表你可能有点懵,它是啥东西,那么,我来告诉你,描述符表里面存放的是描述符,而描述符中就存放了线性的地址的基地址,我讲到这里,大家终于看到了线性地址的身影,
描述符中既然存放了基地址,那么就可通过基地址加上虚拟地址这个偏移量来算出线性地址了。
虚拟地址到线性地址的转换关系图
现在,我更想告诉大家一个结果,那就是虽然虚拟地址和线性地址是有转换关系的,但是在LINUX系统上,段描述符中的线性地址的基地址都是从0开始的,所以,会推算出,虚拟地址和线性地址是相等的,这回明白了吧,讲了半天虚拟地址和线性地址的转换,到头来原来虚拟地址和线性地址是相等的。
接下来,就讲讲线性地址是如何映射物理内存的,只需要一张图,就能看明白:
虚拟地址到物理地址转换的整体架构图
依据以下步骤进行转换:
1. 从CR3寄存器中取出页目录的地址。
2. 根据线性地址中的前10位,找到页目录的索引。
3. 根据页目录项的值与中间10位相加后得到页表中的索引。
4. 将页的起始地址与最后的12位相加后得到最终的物理地址。
结论:
在Linux系统上,虚拟地址和线性地址是相等的。
通过线性地址可以找到页目录中的页表,然后找到页表中的页表项,最终通过页表项和线性地址中的偏移,来找到最终的物理地址。
xnfh1996: 引用「rxw」 rxw,博主帮忙提供下xml、两个摄像头驱动文件,谢谢
boki_education: mjpg-streamer那个git似乎已经失效了
m0_71300969: mqtt
初学者m-: 你好 soft_reset这个函数 软件复位 是指的什么? 是控制MCP2515的reset引脚拉低一段吗?
zhaodaola: Linux服务器基准性能测试常用工具 https://bjzhanghao.com/p/3366