32位 vs 64位系统
2^32=4GB
2^64=2^32*4GB
我们通常所说的手机4+64,4指的是物理内存,64指磁盘大小
而2^32=4GB
的4GB指虚拟内存,是提供给计算机同时运行的程序所需的地址空间的最大值,比如现在实际物理内存大小为2GB,32位系统的话,虚拟内存就是4GB,在代码里申请一个数组,这个数组的最大内存是4GB(和物理内存无关)
计算机在物理上通过32根总线实现32位,64根总线实现64位
物理地址 vs 虚拟地址
我们可以把物理内存看成一个大数组,其中每个字节都可以通过与之唯—对应的地址进行访问,这个地址就是物理地址
在应用程序或操作系统运行过程中,CPU通过总线发送访问物理地址的请求,从内存中读取数据或者向其中写入数据
在引入虚拟内存后,应用程序使用虚拟地址访问存储在内存中的数据和代码,在程序运行过程中,CPU会把虚拟地址转换成物理地址,然后通过物理地址访问物理内存。虚拟地址转换成物理地址的过程通常被称为地址翻译。
MMU内存管理单元
实现虚拟内存需要进行虚拟地址和物理地址之间的切换,这样程序才能正常执行。
要转换就必须要转换机构,它相当于一个函数:p=f(v),其中输入虚拟地址 v,输出物理地址 p。
那么要怎么实现这个函数呢?
用软件方式实现太低效,用硬件实现没有灵活性,最终就用了软硬件结合的方式实现,它就是 MMU(内存管理单元)。MMU 可以接受软件给出的地址对应关系数据,进行地址转换,输出物理地址。
我们先来看看逻辑上的 MMU 工作原理框架图。如下图所示:
上图中展示了 MMU 通过地址关系转换表,将 0x80000~0x84000
的虚拟地址空间转换成 0x10000~0x14000
的物理地址空间,而地址关系转换表本身则是放物理内存中的。
分段 vs 分页
MMU将虚拟地址翻译为物理地址的主要机制有两种:分段机制和分页机制
分段
分段机制下,不仅虚拟内存空间被划分成不同长度的段,物理内存也以段为单位进行分配,在虚拟地址空间中,相邻的段所对应的物理内存中的段可以不相邻,因此操作系统能够实现物理内存资源的离散分配。
但是这种段式分配方式容易导致内存碎片,即在段与段之间留下碎片空间(不足以映射给虚拟地址空间中的段),从而造成物理内存资源利用率的降低
分页
主流的选择分页
多级页表
单级页表下,对于64位虚拟地址空间,页表所占的内存空间太大了,所以采用多级页表进行空间压缩优化
看看32位地址空间和64位下单级页表有多大:
32位地址空间下:
一页4K,页表项4B(一页由一个页表项唯一标识),那么一张记录所有地址空间的页表需要2^32 / 4K 个页表项,
那么这个页表的大小为:`2^32 / 4K * 4 = 4MB`,可以接受
64位地址空间下:
页4K,页表项8B,
页表大小:`2^64 / 4K * 8 = 33,554,432 GB` 太大了无法接受
多级页表实现页表大小的压缩:
为什么单级页表中的每一项都需要存在?
—个64位的虚拟地址在逻辑上被划分成如下几个部分:
注意,64位下虚拟地址最大只有2^48
,因为2^64
太大了没有必要,所以48-63设置为全1或全0了
多级页表结构图:
多级页表寻址过程原理:
局部性原理
时间局部性:被访问过的数据很可能会再次被访问,所以将访问过的数据放入缓存
空间局部性:被访问过的数据的附近的数据
很可能会被访问。所以读数据时预读出其附近的数据。
快表TLB
快表TLB可以加速由虚拟地址得到物理地址的过程,核心原理就是时空局部性原理。
TLB中的一条缓存项对应着一个内存页,由于内存访问的时空局部性,TLB缓存项在将来很可能会被多次查询,即TLB命中的可能性较大。
TLB刷新
为什么需要刷新TLB?
刷新TLB开销大,为TLB打上“标签”来避免开销:
不过,在修改页表内容之后,操作系统还是需要主动刷新TLB以保证TLB缓存和页表项内容一致
内存的分配与回收
虚拟内存
进程中有多少个段表、多少个页表?
进程一定拥有自己的段表|页表,具体有多少?不同的操作系统的在内存储器管理上,使用的方法可能是不一样,不能一概而论。针对我们常见的PC操作系统而言,一般:
1、如果存储器采用基本分页机制,那么操作系统会为每个进程或任务建立一个页表(这个页表可能是一级的也可能是多级的)。整个操作系统中有多个进程在运行,那么系统就会有多个页表。页表在内存中的存储位置由寄存器CR3给出。
2、 如果存储器采用基本分段机制,那么操作系统会为每个进程或任务建立一个段表(一般不用多级),用于记录数据段、代码段等各类段在内存中的具体位置。
3、 如果采用段页式结合的机制,那么一般一个进程或任务,操作系统会给其建立一个段表,而段表中的每个段又会对应一个页表,也就是说,段页式机制的每个进程有一个段表,有多个页表。
总结:
基本分页机制:一个进程有一个页表
基本分段机制:一个进程有一个段表
段页式机制:一个进程有一个段表多个页表