以实际系统的案例来总结一下对虚拟内存的考虑。
注意一点,虽然我们说64位系统,而且处理器体系也允许64位的虚拟地址空间,但是实际上,Core i7现在只是支持48位(256TB)虚拟地址空间和52位(4PB)物理地址空间,兼容支持32位(4GB)地址空间。
Core i7的地址翻译
先看个图
core i7内存系统.png
翻译概况如下图
翻译概况.png
VPN是virtual page number虚拟页号,VPO是virtual page offset虚拟页偏移
注意的几点:
- PTE(page table entry)有三个权限位,控制对页的访问,分别是R/W控制读写,U/S是否能在用户模式中访问,XD(禁止执行),禁止从某些内存页取指令,防止缓冲区溢出共计
- MMU翻译虚拟地址时,还会更新另外两个内核缺页处理程序会用到的位。A位称为引用为,内核用这个引用位来实现它的页替换算法。D位(修改位/脏位),告诉内核在复制替换页之前是否必须写回牺牲页
下面的图给出Core i7如何使用四级页表来将虚拟地址翻译成物理地址的。36位VPN被划分为四个9位的片,每个片被用作到一个页表的偏移量,CR3寄存器(控制寄存器3)包含L1页表的物理地址。VPN1提供到一个L1 PTE的偏移量,这个PTE包含L2页表的基地址。VPN2提供一个到L2 PTE的偏移量,以此类推。
i7页表翻译.png
Linux虚拟内存系统
一个linux进程的虚拟内存.png再来回顾一下linux为每个进程维护的单独的虚拟地址空间,分为内核虚拟内存和进程虚拟内存。
- 内核虚拟内存包含内核中的代码和数据结构。内核虚拟内存的某些区域被映射到所有进程共享的物理页面。例如,每个进程共享内核的代码和全局数据结构,有趣的是,linux也将一组连续的虚拟页面(大小等于DRAM)映射到相应的一组连续的物理页面,为内核提供了便利的方法来访问物理内存中的任何特定位置
内核为系统中每个进程维护一个单独的任务结构,包含或指向内核运行该进程所需要的所有信息(如PID,指向用户栈的指针,可执行目标文件的名字,以及程序计数器PC)。
linux组织虚拟内存.png
mm_struct描述了虚拟内存的当前状态,其中两个字段,
- pgd指向第一级页表(页全局目录)的基址,当内核运行这个进程,就将pgd存放在CR3控制寄存器
- mmap指向一个vm_area_struct(区域结构)的链表,其中每个vm_area_struct都描述了当前虚拟地址空间的一个区域。
- vm_prot 描述读写许可权限, vm_flags 描述这个区域的页面时与其他进程共享还是私有
linux缺页异常处理
- 虚拟地址A是合法的吗?是在某个区域结构定义的区域内吗?缺页处理程序搜索区域结构链表(在链表中构建树来查找),如果不合法,触发一个段错误,终止进程。对应图中情况1
- 试图进行的内存访问是否合法?权限对吗?对应图中情况2
- 如果是对合法虚拟地址的合法操作,那么就选择一个牺牲页面,如果这个牺牲页面被修改过,就将它交换出去,换入新的页面并更新页表。
小结
OK,通过对Core i7/Linux内存系统的实际分析,把我们学过的理论知识包括操作系统的概念与实际的应用结合起来了,完美。
网友评论