1.概念

物理地址:物理地址空间是实在的存在于计算机中的一个实体,在每一台计算机中保持唯一独立性。我们可以称它为物理内存;如在32位的机器上,物理空间的大小理论上可以达到2^32字节(4GB),但如果实际装了512的内存,那么其物理地址真正的有效部分只有512MB = 512 * 1024 KB = 512 * 1024 * 1024 B(0x00000000~0x1fffffff)。其他部分是无效的。

虚拟地址:虚拟地址并不真实存在于计算机中。每个进程都分配有自己的虚拟空间,而且只能访问自己被分配使用的空间。理论上,虚拟空间受物理内存大小的限制,如给有4GB内存,那么虚拟地址空间的地址范围就应该是0x00000000~0xFFFFFFFF。每个进程都有自己独立的虚拟地址空间。这样每个进程都能访问自己的地址空间,这样做到了有效的隔离。

在上面我们提到了合理的内存管理机制。我们这里虚拟地址和物理地址之间的映射是通过MMU(内存管理单元)来完成的。
在这里插入图片描述
MMU:将虚拟的地址转化为物理地址。
段错误:内存访问非法,内核空间受保护
堆空间存储后一定要释放

优点:

1.既然每个进程的内存空间都是一致而且固定的,所以链接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际的内存地址,这是有独立内存空间的好处。

2.当不同的进程使用同样的代码时,比如库文件中的代码,物理内存中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存。

3.在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片。

另外,事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,具体就是初始化进程控制表中内存相关的链表,实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射),等到运行到对应的程序时,才会通过缺页异常,来拷贝数据。还有进程运行过程中,要动态分配内存,比如malloc时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做相应设置,当进程真正访问到此数据时,才引发缺页异常。

在这里插入图片描述

在这里插入图片描述
在进程里平时所说的指针变量,保存的就是虚拟地址。当应用程序使用虚拟地址访问内存时,处理器(CPU)会将其转化成物理地址(MMU)。

这样做的好处在于:
进程隔离,更好的保护系统安全运行
屏蔽物理差异带来的麻烦,方便操作系统和编译器安排进程地址

推荐一篇好文
https://www.cnblogs.com/clover-toeic/p/3754433.html

https://blog.csdn.net/qq_38526635/article/details/81981971?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164552919516780269823158%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164552919516780269823158&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogsobaiduend~default-1-81981971.nonecase&utm_term=RAM+ROM+cpu&spm=1018.2226.3001.4450

https://www.jianshu.com/p/b6356e0ec63c

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐