一、几个基本的概念
1.存储器的金字塔结构
存储器从下之上依次是磁盘/flash、DRAM(内存)、L2-cache、L1-cache、寄存器,越在上面的存储器访问速度越快,同时价格也越昂贵,每一级都可以看做是下一级的缓存,内存是磁盘的缓存,cache是内存的缓存。
2.地址空间
地址空间就是一个非负正数的有序集合,如果是连续的即线性地址空间,从硬件的角度看就是处理器所能访问的存储器空间,与地址线的位数相关,物理地址空间就是物理存储器的访问空间(按字节访问)
3.页
将物理内存和虚拟内存按页来划分,页的大小也有所不同,ARM中支持1M的大页,4k或64k的细页,x86下支持4M的大页,利用页表来表征整个地址空间,当采用二级页表时,存在一个页目录,用来索引对应页表所在的物理地址,PTE页表项占4个字节,当采用4k大小的页时,一个虚拟地址可以划分为:
31 22 21 12 11 0
| 页目录索引 | 页表索引 | 页内偏移 |
硬件页表项PTE
31 22 0
| 物理页帧号 | 物理页属性和访问控制 |
二、地址转译
地址的转译是有虚拟地址至物理地址,处理器内使用的是虚拟地址,经过MMU转译为物理地址,例如DMA使用的就是物理地址,因为它在MMU之后,转译的过程是MMU与OS配合完成的,OS负责维护页表,MMU负责翻译,要明确一点是MMU使用的是物理地址。首先根据页目录的物理地址(x86在CR3中)和页目录索引查找到页目录表项PDE,其中记录了对应页表的物理地址,如果该页表在物理内存中(页表也可以被换出到磁盘中),PDE表项的格式与硬件PTE基本一致,然后根据页表索引找到对应的页表项PTE,最后根据其中的物理页帧号和页内偏移计算得到物理地址。
具体的翻译过程用一个例子来说明:
例如:一个虚拟地址为0x50001,页目录索引为0x0,页表索引为0x50,页内偏移为0x1,首先找到PDE(windows的虚拟地址空间PDE_0的VA = 0xc0300000),PDE物理地址 = CR3 + 0x0(页目录索引)*4,PDE表项内容为0x00700 067,查找PTE,PTE物理地址 = 0x700 + 0x50(页表索引)*4,(PTE的虚拟地址为0xc0000140),PTE表项的内容为0x00e63 047,则最终转译的物理地址 = 0xe63 000 + 0x1 = 0xe63001
三、虚拟内存的原理
如何在物理内存有限的情况下例如只有32MByte,可以使系统寻址4G的地址空间,物理内存资源是一种共享的稀缺资源,因此虚拟地址空间的页并不是都有对应的物理内存页面,将某一时刻处理器不访问的虚拟页面以页的方式保存在磁盘上,当需要读写时再将其换入至物理内存中。
四、进程虚拟地址空间
x86体系结构下,一个进程的虚拟地址空间为4G,主要包括了进程的私有地址空间和系统地址空间两部分,windows中0x0--0x7fff ffff作为进程私有,0x8000 0000 -- 0xffff ffff为系统地址空间。
1.大页和小页
采用大页的好处是在TLB中可以缓存更大的地址空间,增加了缓存命中的概率,不好的一点是页面粗粒度造成的不安全访问,例如.data(读写)和.text(只读)都放在同一个具有读写权限的页面内,则有可能造成.text的内容误写,可能导致系统崩溃。
采用小页的好处是细粒度管理内存,更加灵活,更少的内部碎片,但同时PFN更多,管理的开销要更大一些。
因此为了安全可靠,选用小页,4K page
2.延迟计算
(1)先保留再提交内存
当一个线程申请大块的虚拟内存时,现在虚拟地址空间中保留一段范围,为一块虚拟内存建立虚拟地址描述符(VAD),当真正访问这段地址空间时,再建立PTE,也就是在物理内存中分配有效的页面。一个应用例子就是每个线程的用户栈在创建时首先会保留1MB的空间,只有在虚拟页面被访问时才会提交。在VAD中记录了地址范围的大小,以及读写权限,当建立PTE时就根据VAD中记录的信息(读写权限)来填充PTE。
(2)写时复制 copy-on-wirte
i.当两个进程共享一个写时复制的物理页面时,如果其中一个进程中的线程要对共享页面进行写操作,则产生一个内存管理错误(一个异常),内存管理器为其分配一个新的读写物理页面,并且将原始共享页面的内容复制到新的物理页面中,并将虚拟地址映射更新为新的物理页面,控制权返回线程,线程执行写操作,此时新的物理页面属于该进程私有,其他进程是看不到的,也就是说写时复制为执行写操作的进程创建了一份私有的拷贝。
ii.POSIX子系统利用写时拷贝来创建子进程的地址空间,首先父进程创建一个子进程,子进程的地址空间是共享父进程的地址空间,将地址空间标记为写时拷贝,只有子进程执行写操作时,才会拷贝相应的页面给子进程私有使用。
3.内存区对象
section object,每一个打开的文件都有一个内存区对象指针,根据文件类型的不同(数据文件或可执行文件)指向不同的控制区域(虚拟地址空间内),控制区域包括子内存区,例如一个可执行文件的子内存区就是.data,.text,.bss等,同时这个控制区域又指向了一些原型PTE,通过这些原型PTE可映射到该内存区对象所映射的实际物理页面。
当内存区对象指向一个很大的数据文件时,线程只访问其中的一部分,就只映射该内存区中的一部分,这部分被称为内存区视图。
内存区对象的应用,映像加载器利用它加载可执行文件,缓存管理器利用它来访问缓存文件中的数据,这两者都是针对打开的文件,共享内存的应用是内存区对象与物理内存关联。
虚拟页有三种状态,已提交的,保留的和未分配的。
4.windows的四种内存保护机制
(1)系统空间的全局数据结构和内存池只有在内核模式下才可以访问,用户线程无法访问这些页面
(2)每个用户进程都有自己的私有地址空间,这部分空间是其他进程无法访问的
(3)地址转译过程中的隐式保护,一个标记为只读的页在对其进行写操作时会产生页面访问错误
(4)共享内存区对象具有标准的windows访问控制列表,对于没有权限的进程,是无法访问共享内存区的
5.进程页表
一个进程有自己的页目录,这个页目录就指向了对应的页表,进程的系统空间都是共享的,因此页表也是共享系统空间页表项,一个进程在创建时会初始化地址空间,也就是初始化页表,第一阶段就是创建系统空间的页表项,就是将页目录的PDE指向系统空间的页表,然后是打开一个可执行文件建立一个内存区对象,再映射至进程的私有空间,实质上是先保留地址空间,当进程执行时根据读写页面的需要创建PTE,进程的会话空间页表也是共享的,即指向已有的会话页表。进程的页目录和页表所在的物理页被映射至0xc0300 000和0xc000 0000
6.TLB
TLB就是缓存了虚拟页至物理页的映射,本质上就是一个cache,进程切换时会刷新TLB,但是系统空间的TLB项不会刷新,因为进程的系统空间是共享的
7.页面错误处理
页面处理的错误有两种,(1)访问了没有物理页映射的虚拟地址 (2)以错误的方式访问
8.原型PTE
首先原型PTE是一种无效PTE,目的是让所有可能需要共享页面的进程的PTE都指向原型PTE来解决页面错误,原型PTE是伴随这共享页面的内存区一起创建的,当共享内存页面是有效时,进程都直接用自己的PTE来访问。
当共享内存页面无效时,如果没有原型PTE,那如果一个进程访问该共享页面将其换入内存中,那内存管理器要将所有共享该内存页的进程的页表进行更新,告诉他们共享内存页有效了,这样做比较费力。
现在使用原型PTE,当进程访问的共享页无效时,则将该PTE指向共享页的原型PTE,如果进程A再次访问该页,共享页又被换入内存中,此时要更新原型PTE指向新的物理页,当进程B再次访问共享页时,此时因为原型PTE已经得到更新,则内存管理器更新进程B的页表,使其PTE指向新的物理页。
原型PTE的精髓还是延迟计算,就是当一个共享页从新被换入内存时,不必去更新所有曾经访问过该共享页的进程页表,而是等到进程真正访问时再去更新。
9.换页策略
(1)最近最少使用
(2)先进先出 将驻留在内存中最久的页面换出
(3)时钟算法
- Windows内核 内存管理基本概念
内存管理概念: 1)物理内存 PC上有三条总线:数据总线.地址总线和控制总线.32位CPU的寻址能力是4GB个字节,用户最多可以使用4GB的真实物理内存.PC中很多设备都提供了自己的设备内存,例如显卡 ...
- linux内核--内核内存管理
如题目所示,为什么要称作“内核内存管理”,因为内核所需要的内存和用户态所需要的内存,这两者在管理上是不一样的. 这篇文章描述内核的内存管理,用户态的内存管理在以后的文章中讲述. 首先简单的说明一下下面 ...
- Linux内核内存管理架构
内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射.页面分配.页面回收.页面交换.冷热页面.紧急页面.页面碎片管理.页面缓存.页面统计等,而且对性能也有很高的要 ...
- Linux内核内存管理算法Buddy和Slab: /proc/meminfo、/proc/buddyinfo、/proc/slabinfo
slabtop cat /proc/slabinfo # name <active_objs> <num_objs> <objsize> <objpersla ...
- Linux0.11内核--内存管理之2.配合fork
[版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5598451.html ] 在上一篇的fork函数中,首先一上来就调用get_free_page ...
- Linux0.11内核--内存管理之1.初始化
[版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5597705.html ] Linux内核因为使用了内存分页机制,所以相对来说好理解些.因为内存 ...
- Linux内核内存管理子系统分析【转】
本文转载自:http://blog.csdn.net/coding__madman/article/details/51298718 版权声明:本文为博主原创文章,未经博主允许不得转载. 还是那张熟悉 ...
- (笔记)Linux内核学习(九)之内核内存管理方式
一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...
- Linux内核学习笔记——内核内存管理方式
一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...
随机推荐
- iOS 关于iOS开发中的delegate
有A.B两个对象,A要完成某件事,想让B帮它做. 这时候,A中就要实例化一个B的对象b,A还要在头文件中声明协议,然后在B中实现协议中对应的方法. 这时候再把A的delegate设置为b,在需要的地方 ...
- docker不稳定 short running containers with -rm failed to destroy
正常运行以下命令 sudo docker run --rm busybox echo helloworld /var/log/upstart/docker.log 日志如下: // :: POST / ...
- CF#335 Lazy Student
Lazy Student time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- unity MenuAnim.MoveTo
移动函数,第一个参数是gameobject,第二个参数是pos,第三个参数是时间,第四个参数延迟 MenuAnim.MoveTo(title, new Vector3(1, 0.7f, 0), 0.5 ...
- 关于struts2中表单提交时,中文乱码问题的解决
http://blog.csdn.net/hjw506848887/article/details/8966194 今天写项目时,突然遇到了struts2中表单提交的中文乱码问题,调了好久就是不知道答 ...
- ACM:POJ 2739 Sum of Consecutive Prime Numbers-素数打表-尺取法
POJ 2739 Sum of Consecutive Prime Numbers Time Limit:1000MS Memory Limit:65536KB 64bit IO Fo ...
- [总结]HNOI2015省队选拔
// 此博文为迁移而来,写于2015年4月21日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vy9t.html 这次省 ...
- 【POJ】3133 Manhattan Wiring
http://poj.org/problem?id=3133 题意:n×m的网格,有2个2,2个3,他们不会重合.还有障碍1.现在求2到2的路径和3到3的路径互不相交的最短长度-2.(2<=n, ...
- iOS 开发小结
一,经历 1> 在编写以前有过的类似的新功能时,如果以前的开发人员没有写明明确的注释和开发需求,一定要仔细阅读所有代码,每一句代码都有它存在的意义. 2> 例如,只以为是[self.ful ...
- 整理iOS9适配
整理iOS9适配 本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iOS9正式版, ...