虚拟内存

来源:互联网 发布:淘宝网天猫手机支架 编辑:程序博客网 时间:2024/06/05 14:12

虚拟内存机制概念

在没有虚存机制的计算机中,程序指令所访问的内存地址就是物理内存地址。但实际上程序不必全部载入内存,一方面内存资源有限另一方面即使在需要完整程序的时候,也并不是同时需要所有的程序而在有虚存机制并且打开的情况下,程序指令所访问的内存地址都是虚拟内存地址。某个虚拟内存的地址可以通过设置被映射到任何物理内存地址,虚拟内存(virtual memory)将用户逻辑内存和物理内存分开。这在现有物理内存有限的情况下,为程序员提供了巨大的虚拟内存,如同3-1所示。

虚拟内存为每一个进程提供了一个够大的,统一的,私有的地址空间(虚拟地址空间)。在一个非常清晰的机制下面,虚拟内在提供了三种重要功能:

  • 将主存作为磁盘文件的cache. 存放在主存上面的仅仅是用得着的,活跃部分。只有在有需要的时候,将数据从磁盘搬到内存上,或者换回去
  • 它简化了内存管理,为每一个进程提供统一的地址空间
  • 它保护了一个进程的地址空间不被其他进程破坏

程序运行时,虚存地址到物理地址的转换工作是由专门的硬件完成的,它叫做内存管理单元(Memory Management Unit,MMU)。转换过程如图3-2所示。

从图3-2中可以看出,当CPU访问某虚存地址时,不管是读指令或读写数据,该地址首先会被发送给内存管理单元进行转换。在获得转换后的物理地址后,CPU再对该物理地址进行读写操作。

虚拟内存机制工作机制

1.为什么要有虚拟内存
在早期的计算机中,是没有虚拟内存的概念的。我们要运行一个程序,会把程序全部装入内存,然后运行。
当运行多个程序时,经常会出现以下问题:
1)进程地址空间不隔离,没有权限保护。
由于程序都是直接访问物理内存,所以一个进程可以修改其他进程的内存数据,
甚至修改内核地址空间中的数据。
2)内存使用效率低
当内存空间不足时,要将其他程序暂时拷贝到硬盘,然后将新的程序装入内存运行。
由于大量的数据装入装出,内存使用效率会十分低下。
3)程序运行的地址不确定
因为内存地址是随机分配的,所以程序运行的地址也是不确定的。

2.虚拟地址和物理地址
对于32位系统,寻址指针为4字节,对应的虚拟地址空间为0-2^32,即0-4G。
对于64位系统,寻址指针为8字节,对应的虚拟地址空间为0-2^64,即0-16G。
要注意的是,这个地址空间是虚拟的,并非实际存在的
Linux内核把虚拟地址空间分为两部分:用户进程空间,内核进程空间。
如下入所示:

在缓存原理中,换入/换出的数据以块为最小单位。在内存管理时,页是地址空间的最小单位
虚拟地址空间划分为多个固定大小的虚拟页(VP),物理地址空间(DRAM内存)划分为多个固定大小的物理页(PP),
虚拟页和物理页的大小是一样的,通常为4KB。

虚拟页和物理页存在着以下关系:
虚拟页和磁盘文件映射,然后缓存到物理页。
根据是否映射,是否缓存,可以将虚拟页的状态分为以下三种:
1)未映射的页
即虚拟页没有映射到磁盘文件
2)未缓存的页
虚拟页映射到了磁盘文件,但是没有缓存到物理页,也就是内存上。
3)缓存的页
虚拟页映射到了磁盘文件,并且缓存到物理页
如下图所示:

3.虚拟地址的工作原理
对于进程来说,使用的都是虚拟地址。每个进程维护一个单独的页表。何为页表?
页表是一种数组结构,存放着各虚拟页的状态,是否映射,是否缓存。

1)数组的索引号,表示虚拟页号
2)数组的值
若为null,表示未映射的页
若非null,第一位表示有效位,为1,表明缓存的页;为0,表明未缓存的页。
其余位表示缓存到的物理页号。

页表结构图如下:

进程执行时,当需要访问虚拟地址中存放的值时,步骤如下:
1)CPU会先找到虚拟地址所在的虚拟页(VP3),根据页表,找出页表中第3条的值。
判断有效位,为1,DRMA缓存命中,获根据物理页号,找到物理页中的内容,返回。
2)若有效位为0,产生缺页异常,调用内核缺页异常处理程序。
它会选择一个物理页(如PP4),作为牺牲页,将该页的内容刷新到磁盘文件。然后,把VP3映射的磁盘文件,缓存到该物理页。
页表中的第3条,有效位变1,同时,物理页号表号变为PP4。
3)缺页异常处理完毕后,返回中断前的指令,重新执行,此时缓存命中,执行1)
4)将找到的内容映射到高速缓存,CPU从高速缓存中获取该值,结束。

4.使用虚拟地址需要注意的问题
1)磁盘和主存传送页的活动叫做页面调度。页面调度会引起磁盘流量,如果程序的局部性不好,会频繁进行页面调度,叫做“缓存颠簸”。
操作系统会在内存中分配一块交换区作为缓冲区,来加速页面的调度。
2)一级页表占用的空间是比较大的,根据按需调度的原则,一般使用的是多级页表,即一级页表指向二级页表,这样大大压缩了页表的大小。

5.地址翻译
地址翻译指的是DRAM缓存命中时,由虚拟地址找到物理地址的过程。
该过程是完全由硬件来完成的。
1)CPU有一个专门的页表基地址寄存器(PTBR)指向当前页表的基地址,快速定位到该进程的页表。
2)根据虚拟页号,找到虚拟地址在页表的值。
3)根据值中的物理页号,找到物理地址。

6.Linux中的虚拟内存机制

Linux把虚拟内存划分成区域area的集合,一个area包括连续的多个页。
area的数据结构如下所示:
1)内核为每个进程维护了一个单独的任务结果task_struct
2)task_struct的mm指针,指向了mm_struct,该结构描述虚拟内存的运行状态。
3)mm_struct的pgd指针指向进程的一级页表的基地址
mmap指针,指向vm_area_struct链表。
4)vm_area_struct描述area的结构,vm_start表示area的开始位置,vm_end表示area的结束位置,vm_prot表示area内的页的读写权限,vm_flags表示area内的页面是进程私有还是共享,vm_next指向下一个area节点。

在Linux中,当发生缺页异常时,步骤如下:
1)缺页异常程序,检查虚拟地址在哪个area内。
2)访问的虚拟页若没有读写权限,则触发一个保护异常,终止进程。
3)选择牺牲页,刷新到磁盘,从磁盘加载缺失的内容到物理页,更新页表。

7.Linux虚拟内存需要注意的问题
内存映射机制:初始化虚拟内存区域时,会把虚拟内存和磁盘文件对象对应起来。

由于内存映射机制,一个磁盘文件对象可被多个进程共享访问,也可被多个进程私有访问。
当共享访问时,一个进程的对该对象的修改会显示到其他进程。
当私有访问时,修改时会产生保护故障,内核会拷贝这个私有对象,修改的是这个新对象,其他进程指向的是原来的对象。

fork函数是说明内存映射机制很好的例子:
fork函数会创建带有独立虚拟地址空间的新进程,内核会把当前进程的虚拟内存中数据结构复制一份给新进程。虚拟内存area包括共享区域和私有区域,新建的进程对私有区域做修改时,会触发写时拷贝,为新进程维护私有的虚拟地址空间。

8.虚拟地址作用总结
1)虚拟内存管理可以控制物理内存的访问权限
访问的虚拟页若没有读写权限,则触发一个保护异常,终止进程。
2)虚拟内存让每个进程有独立的地址空间
对于私有区域来说,当不同进程对该区域做修改时,会触发写时拷贝,为新进程维护私有的虚拟地址空间。
3)VA到PA的映射会给分配和释放内存带来方便。
物理内存不连续的地址,可映射到连续的虚拟内存地址。
4)内存效率高
使用了页面调度,不会造成大量的数据装入装出。

虚拟内存机制优点

1 安全性

虚拟内存是保证系统安全的一个重要机制。它使得各个进程在物理空间上实现隔离,程序只能访问本进程的虚存空间。通过把不同的进程映射到不同的物理内存空间,使得一个进程无法访问另一个进程空间的数据(进程间自愿共享的内存和其他有意的通信方式除外),如图3-3所示。

而且,通过虚存机制,操作系统可以使用两套不同的映射寄存器将用户空间和内核空间分布映射到不同的物理空间,从而杜绝了用户程序直接访问内核空间的可能。位于用户模式下用户程序只能通过系统调用来访问内核空间,而这是处于可信软件—操作系统的控制下,所以这样的访问是安全的。

另外,利用虚存机制可以设定某些页面的访问权限,如只读、读写等,从而保护页内数据不受破坏。比如,代码为了防止在运行时被程序不小心修改,其一般设为只读。对进程空间的不同段设置不同的访问权限的情况如图3-4所示。

2 提高内存利益率

利用虚存机制还可以充分利用物理内存空间。比如PDP 11/40总线实际上支持18位地址模式,最大物理空间可达256k。但程序指令只能访问16位64k地址空间,如果没有虚存机制那么物理内存只有0~64k可以被指令访问,而其他空间由于CPU位数限制而无法被访问,有了虚存机制,这256k内存空间都可被使用,通过虚拟内存,程序指令可以访问比CPU位数高内存地址的情况如图3-6所示。

3 多线程支持

利用虚存机制,每个进程可以单独编译,独立分配地址空间。也就是说,对于一个16位的进程,编译器可以在其64k地址空间内随意分配代码区和数据区,而不用担心和其他进程空间冲突,因为这64k空间完全属于该进程。而且,操作系统可以把多个进程同时载入内存运行,因为它们可以被映射到不同的物理内存。如果没有虚拟内存,则没法实现这一点,这时两个进程都要求使用0~64k的物理空间,这样同一时刻只能哟一个进程在内存中运行。

而且虚拟内存使得进程交换成为可能。出于内存分配的需求,内核经常根据一些策略把某些进程换出到磁盘上,以腾出空间供其他进程使用。而过一段时间后,这些进程还会被换回内存中继续运行,但它们被换人后所分配的物理地址并不要求和换出前一样,可以是任意地址。
原创粉丝点击