虚拟内存 Virtual Memory

物理地址和虚拟地址

把主存看成是由连续字节单元组成的大数组,并且用物理地址(PA)来标识每个数组的单元。CPU需要加载存储器中一个字都时候,就指定这个字的物理地址的首地址,从而将存储器中的数据返回给CPU,通过物理地址来访问存储器的方式就是物理寻址。所以很直观,物理寻址方便很多,然而对于系统来说,直接物理寻址对存储器的管理很不合理。 

所以有了虚拟地址(VA),通过虚拟地址访问存储器的方式就叫做虚拟寻址,其实这种说法不是很恰当,因为虚拟地址最终还是会被翻译(这个翻译由硬件和系统协同完成的)成物理地址,从而访问存储器,虚拟地址和物理地址是一一对应的

可以看到,最终访问内存的还是物理地址(PA)。

虚拟存储器

虚拟存储器(即虚拟内存),是由N个字节组成的,它存在于磁盘上(注意,是磁盘上,不是存储器内存上)。另外物理存储器和虚拟存储器都是用页来作为磁盘和内存的传输单元。但是CPU是从内存上取数据啊,而虚拟存储器是存在在磁盘上,因此虚拟存储器必须清楚它的哪些页是已分配(里面的数据是有效的)的,哪些是缓存在内存中(将数据从磁盘中拷贝到CPU能较高速访问物理存储器)的,哪些是已分配但是未被缓存到内存中的(数据是有效的且暂时只存在磁盘中,当需要的时候再缓冲)。

神奇的页表

虚拟存储器如何知道它每个页的分配情况呢?页表(PT)从而诞生了,每一个虚拟存储器都有它自己独有的页表,页表为虚拟地址和物理地址的全相联提供了可能。 

因为有页表的存在,所以没有必要把虚拟存储器(再声明,是存在在磁盘上的)的所以页都缓存在内存当中,即便CPU访问该虚拟存储器的页不存在在内存当中,那么系统会通过查表,把需要的页从磁盘当中拷贝到内存当中,这里就涉及了页面调度的复杂算法了(页面置换算法)。

有了页表,CPU也不放心

页命中的情况:如果虚拟页已经缓存到了物理存储器那么好办,直接从物理存储器中直接读取数据就好了。 

还是这张图,来看看简单的命中的情况。假如CPU给出的虚拟地址,地址翻译硬件进行查表,通过虚拟地址定位到了PTE 2(PTE就是页表的条目,上面有注释)的位置,发现它的有效位是1,证明里面的数据是有效的且数据已经缓存到了DRAM当中。所以取出PTE 2中的物理存地址来访问DRAM,可以看到它指向了DRAM中的VP 0,目标查找成功,OVER!!

页不命中(缺页)的情况:
 

如果CPU给出的虚拟地址指向了尚未缓冲的地址。地址翻译硬件发现PTE 5中数据是有效的,但它并没有从磁盘中缓存到DRAM中。地址翻译硬件发现某个CPU需要的虚拟页没有缓存到DRAM中,就会触发一个缺页的异常(产生一个中断),那么对应的缺页异常处理程序就会启动。首先会选择已缓存到DRAM的一个牺牲页,把它拷贝回虚拟存储器的某个位置,再将命中的虚拟页缓存到DRAM当中。 
这时候,异常处理过程返回,重新返回到导致缺页异常的指令,重新执行,目标命中,OVER!!另外,经常缺页会降低程序执行的效率,不命中的处罚还是存在的。

进程离不开虚拟存储器

现在来谈谈操作系统中的进程。操作系统为每个进程都分配了一个页表,也就是说每个一个进程都有虚拟内存,独立的虚拟地址空间。 

可以看到,每个进程都有一张页表,同一个进程的内存空间在虚拟存储器中可以是不连续的,因为虚拟存储器和页表映射加上缺页缓存的机制让进程“拥有”一个“连续”的空间提供了可能,可实际上,是很有可能是不连续的。CPU提取数据的时候,都会先给出的是虚拟地址,无论页命中还是不命中,最后由地址翻译硬件翻译出来的物理地址都不会有错。

在刚开始学c语言的时候经常用到函数scanf和printf等等一些函数,他们在自己进程中有一个虚拟地址与之对应,这样看起来好像每个进程内scanf和printf是分家的,实际上,由于虚拟地址的映射,每个进程中的这些库函数地址都映射到了物理地址的同一个位置,这就节省了很多的空间,从而又不影响进程的独立性。

------------------------------------------------------------------------------------------------------------------------

操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要处理器中的MMU(Memory Management Unit,内存管理单元)提供支持,现在简要介绍MMU的作用。

首先引入两个概念,虚拟地址和物理地址。如果处理器没有MMU,或者有MMU但没有启用,CPU执行单元发出的内存地址将直接传到芯片引脚上,被内存芯片(以下称为物理内存,以便与虚拟内存区分)接收,这称为物理地址(Physical Address,以下简称PA),如下图所示。

如果处理器启用了MMU,CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA),而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将VA映射成PA,如下图所示。

MMU将VA映射到PA是以页(Page)为单位的,32位处理器的页尺寸通常是4KB。例如,MMU可以通过一个映射项将VA的一页0xb7001000~0xb7001fff映射到PA的一页0x2000~0x2fff,如果CPU执行单元要访问虚拟地址0xb7001008,则实际访问到的物理地址是0x2008。物理内存中的页称为物理页面或者页帧(Page Frame)。虚拟内存的哪个页面映射到物理内存的哪个页帧是通过页表(Page Table)来描述的,页表保存在物理内存中,MMU会查找页表来确定一个VA应该映射到什么PA。

操作系统和MMU是这样配合的:

  1. 操作系统在初始化或分配、释放内存时会执行一些指令在物理内存中填写页表,然后用指令设置MMU,告诉MMU页表在物理内存中的什么位置。
  2. 设置好之后,CPU每次执行访问内存的指令都会自动引发MMU做查表和地址转换操作,地址转换操作由硬件自动完成,不需要用指令控制MMU去做。

我们在程序中使用的变量和函数都有各自的地址,程序被编译后,这些地址就成了指令中的地址,指令中的地址被CPU解释执行,就成了CPU执行单元发出的内存地址,所以在启用MMU的情况下,程序中使用的地址都是虚拟地址,都会引发MMU做查表和地址转换操作。

为什么要使用虚拟地址?

1)程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。

2)程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存没有命中时,内存管理器会将最近最不常用的物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。

3)不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程使用的物理内存。

时间: 2024-10-22 09:27:56

虚拟内存 Virtual Memory的相关文章

LDAP实例异常停止日志提示虚拟内存virtual memory不足

[05/Oct/2014:20:50:37 +0800] - ERROR<5135> - Resource Limit - conn=-1 op=-1 msgId=-1 - Memory allocation error calloc of 9420 bytes failed; errno 12The server has probably allocated all available virtual memory. To solve this problem, make more virt

Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十三)kafka+spark streaming打包好的程序提交时提示虚拟内存不足(Container is running beyond virtual memory limits. Current usage: 119.5 MB of 1 GB physical memory used; 2.2 GB of 2.1 G)

异常问题:Container is running beyond virtual memory limits. Current usage: 119.5 MB of 1 GB physical memory used; 2.2 GB of 2.1 GB virtual memory used. Killing container. spark-submit提交脚本: [[email protected] work]$ more submit.sh #! /bin/bash jars=""

[hadoop] - Container [xxxx] is running beyond physical/virtual memory limits.

当运行mapreduce的时候,有时候会出现异常信息,提示物理内存或者虚拟内存超出限制,默认情况下:虚拟内存是物理内存的2.1倍.异常信息类似如下: Container [pid=13026,containerID=container_1449820132317_0013_01_000012] is running beyond physical memory limits. Current usage: 1.0 GB of 1 GB physical memory used; 1.7 GB o

virtual memory exhausted: Cannot allocate memory

问题描述: 购买的Linux服务器,Linux服务器的内存为512MB. 在编译PHP的时候会提示:virtual memory exhausted: Cannot allocate memory,编译失败. 解决方法: 发生该问题的原因是服务器的内存不够,从而导致编译失败. 而购买的Linux服务器,未给你分配虚拟内存,所以可以通过自行增加虚拟内存的方法予以解决 [[email protected] ~]# free -m total used free shared buffers cach

Cache and Virtual Memory

Cache存储器:电脑中为高速缓冲存储器,是位于CPU和主存储器DRAM(DynamicRandonAccessMemory)之间,规模较小,但速度很高的存储器,通常由SRAM(StaticRandomAccessMemory静态存储器)组成.它是位于CPU与内存间的一种容量较小但速度很高的存储器.CPU的速度远高于内存,当CPU直接从内存中存取数据时要等待一定时间周期,而Cache则可以保存CPU刚用过或循环使用的一部分数据,如果CPU需要再次使用该部分数据时可从Cache中直接调用,这样就避

Linux Process Virtual Memory

目录 1. 简介 2. 进程虚拟地址空间 3. 内存映射的原理 4. 数据结构 5. 对区域的操作 6. 地址空间 7. 内存映射 8. 反向映射 9.堆的管理 10. 缺页异常的处理 11. 用户空间缺页异常的校正 12. 内核缺页异常 13. 在内核和用户空间之间复制数据 1. 简介 用户层进程的虚拟地址空间是Linux的一个重要抽象,它向每个运行进程提供了同样的系统视图,这使得多个进程可以同时运行,而不会干扰到其他进程内存中的内容,此外,它容许使用各种高级的程序设计技术,如内存映射,学习虚

mac os 10.10上安装my eclipse显示virtual memory不足,解决方案

mac os 10.10上安装my eclipse显示virtual memory不足,安装失败. 自从把OS 升级到10.10 之后, 各种问题, 安装的时候向导提示提示我们说没有足够的虚拟内存, 其实不是真的没有, 而是系统的内存还够用, 不让你去分配, 因此无法继续安装,当时我心中一紧, 不会要我降级吧 . 研究了看了一段时间的内存检测之后 ,发现像这种蛋疼问题只要我们耍耍流氓 , 打开十个八个软件, 让系统乖乖的打开虚拟内存就可以了. 如图:

ADDM Reports bug:Significant virtual memory paging was detected on the host operating system

查看ADDM(数据库版本为ORACLE 10.2.0.5.0)报告时,发现其中有个结论非常不靠谱:Significant virtual memory paging was detected on the host operating system,具体内容如下所示: FINDING 2: 100% impact (3930 seconds) ------------------------------------- Significant virtual memory paging was d

解决:virtual memory exhausted: Cannot allocate memor

问题描述: 购买的Linux服务器,Linux服务器的内存为512MB. 在编译PHP的时候会提示:virtual memory exhausted: Cannot allocate memory,编译失败. 解决方法: 发生该问题的原因是服务器的内存不够,从而导致编译失败. 而购买的Linux服务器,未给你分配虚拟内存,所以可以通过自行增加虚拟内存的方法予以解决: 1 2 3 4 dd if = / dev / zero of = / swap bs = 1024 count = 1M mks