内存是用于存放数据的硬件,程序执行前需要放到内存中才会被cpu处理。
虚拟内存
为了让应用程序之间高效安全的共同使用物理内存资源(内存管理的目的,物理内存不隔离,分配后不连续),在应用程序和物理内存之间加入新的抽象:虚拟内存。
物理地址:物理内存可以看成一个数组,每个字节对应的地址就是物理地址。
虚拟地址:访问虚拟内存的地址。cpu将虚拟地址翻译成物理地址,进而访问物理内存。
虚拟地址怎么映射到物理地址?
内存管理单元 memory management unit MMU
cpu中的重要部件,负责地址翻译
以下是两种MMU的地址翻译机制
01 分段机制:以段为单位进行内存分配,每个段在内存中占据连续空间,大小不同,各段之间可不相邻。实现物理资源的离散分配。
虚拟地址由两部分组成:
- 段号:虚拟地址属于整个虚拟地址空间的哪一个段
- 段内地址:相对该段起始地址的偏移量。
段表:记录虚拟地址空间中每个段的信息,包括段起始物理地址(基址)和段长。
MMU地址翻译过程:
- MMU通过段表基址寄存器找到段表位置
- 结合段号在段表中定位段的信息,取出该段的起始物理地址;加上虚拟地址中的段内地址得到最终物理地址。
分段机制的缺点:容易导致物理内存上出现外部碎片,即段和段之间留下碎片空间,造成物理内存资源利用率的降低。
02 分页机制:将程序的虚拟地址空间划分成连续的、等长的虚拟页;物理内存也被分为连续的、等长的物理页。优点:方便构造映射关系。
虚拟地址由两部分组成:
- 虚拟页号:用于在应用程序中的页表中找到对应物理页号。
- 页内偏移量
MMU地址翻译过程:
- 通过虚拟页号在页表(页表基地址寄存器)中找到对应的物理页号
- 将物理页号加上虚拟地址中的页内偏移量得到物理地址。
页表:记录虚拟页到物理页的映射关系。
分页机制的优点:
- 虚拟地址空间中的任意虚拟页可以被映射到物理内存中的任意物理页,操作系统能够实现资源的离散分配;
- 分页机制按照固定大小分配物理内存,使得物理资源易于管理,可有效避免外部碎片的问题。
03 多级页表:(页表太大怎么办?)多级页表允许整个页表结构中出现空洞,节约空间。但会导致翻译时长增加,一次页表翻译需要多次访问物理内存。
04 段页式:段页式管理就是将程序分为多个逻辑段,在每个段里面又进行分页。系统为每个进程建立一张段表,而每个分段有一张页表(在一个进程中,段表只有一个,而页表可能有多个)。
转址旁路缓存 translation lookaside buffer TLB
MMU的内部单元,用于减少物理内存的访存次数,加速地址翻译。TLB缓存了虚拟页号到物理页号之间的映射关系。
TLB命中:在缓存中通过虚拟页号找到物理页号,可以无需查询页表直接完成翻译。
TLB未命中:硬件将通过页表基地址查询页表,找到对应的页表项,将其填入TLB缓存中。若此时缓存已满,则根据一定规则替换掉某一项。
在修改页表内容后,操作系统需要主动刷新TLB,以保证TLB缓存页和页表项内容一致。
访问某一个页可能访问多少次内存?
- TLB命中:一次
- TLB未命中:页式和段式都是两次(1. 从内存中找到页表,然后找到页的物理块号,加上页内偏移得到实际物理地址;2. 根据第一次得到的物理地址访问内存取出数据。),如果分多级,多一级一次。
- 段页式:三次。找段表,找页表,找物理内存。
换页与缺页异常
01 换页机制:当物理内存容量不够的时候,操作系统应该把若干物理页的内容写到类似于磁盘这种容量更大更加便宜的存储设备中,然后就可以回收这些物理页供其他程序使用了。
02 缺页异常:它是和换页机制密不可分的,也是换页机制能够工作的前提,当应用程序访问已分配但未映射至物理内存的虚拟页时,就会发生缺页异常。
页替换策略
当空闲物理内存已经小于某个阈值,此时又需要分配物理页时,操作系统需根据页替换策略选择一些物理页换出到磁盘,以让出空间。当已被换出的内存页再次被访问时,需重新从磁盘换入物理内存。页替换策略是依据硬件提供的页访问信息,来猜测需要被换出的页,从而最小化缺页异常的发生次数以提升性能。
01 MIN/OPT策略:minimum/optimal策略,优先选择未来不会再被访问的物理页,或者最长时间内不会被访问的物理页进行换出。操作系统无法预知和实现。
02 FIFO策略:维护先进先出队列,时间开销低,实际使用表现不佳。Belady异常—当为进程分配的物理块数增大时,缺页次数不减反增的异常现象。
03 Second Chance 策略:维护FIFO队列记录物理页号,同时为每个页号记录访问标志位,如果访问的页号已存在,则添加标志。淘汰时,如果对象被引用过,该对象标志位清零,重新插入队列尾部,像新的对象一样;如果该对象未被引用过,则将被淘汰。
04 LRU策略:在选择换出页时,优先选择最久未被访问的页。硬件开销较大。
05 时钟算法策略CLOCK/最近未用算法NRU:开销较为均衡,为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列。当某页被访问时,其访问位置为1。当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出; 如果是1,则将它置为0,暂不换出,继续检查下一个页面,若第一轮扫描中所有页面都是1,则将这些页面的访问位依次置为0后,再进行第二轮扫描(第二轮扫描中一定会有访问位为0的页面,因此简单的CLOCK算法选择–个淘汰页面最多会经过两轮扫描)。
06 改进后的时钟算法:增加修改位表示页面是否被修改过,在其他条件都相同时先淘汰未被修改过的页面,不需要进行I/O操作将其写回外存。
工作集模型
抖动/颠簸现象:频繁的页面调度(换入/换出页面)行为。产生抖动的主要原因是进程频繁访问的页面数目高于可用的物理块数(分配给进程的物理块不够)。
为进程分配的物理块太少,会使进程发生抖动现象。为进程分配的物理块太多,又会降低系统整体的并发度,降低某些资源的利用率。
工作集模型:为了研究为应该为每个进程分配多少个物理块。驻留集大小不能小于工作集大小,否则进程运行过程中将频繁缺页。
- 驻留集:指请求分页存储管理中给进程分配的内存块的集合。
- 工作集:指在某段时间间隔里,进程实际访问页面的集合。
让操作系统跟踪每个进程的工作集,并为进程分配大于其工作集的物理块。如果还有空闲物理块,则可以再调一个进程到内存以增加多道程序数。如果所有工作集之和增加以至于超过了可用物理块的总数,那么操作系统会暂停一个进程,将其页面调出并且将其物理块分配给其他进程,防止出现抖动。
虚拟内存功能
01 共享内存:同一个物理页在不同程序间共享,让不同应用程序间进行通信和数据传递。
02 写时拷贝:一个页表项可记录用于标识虚拟页权限的权限位,写时拷贝是利用“是否可写”权限位实现的。
两个程序以只读方式共享同一段清楚可写权限的物理内存,一旦某一方进行修改,就会造成由违反权限导致的缺页异常。操作系统会将物理内存拷贝一份并以可读可写的方式映射给程序,此后恢复程序执行。
优点:节约物理资源,避免内存拷贝带来的时间空间开销。
fork():内核只为新生成的子进程创建虚拟空间结构,它们来复制于父进程的虚拟nei结构,但是不为这些段分配物理内存,它们共享父进程的物理空间,当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间。
vfork():子进程直接共享了父进程的虚拟空间和物理空间。
03 内存去重:操作系统定期扫描具有相同内容的物理内存页,以及它们的虚拟页,只保留一个物理页,并将所有虚拟页以写时拷贝的方式映射过去,释放其他物理页。
缺点:会对应用程序的访存时延造成影响,程序修改内存时需要写时拷贝导致性能下降。
04 内存压缩:当内存资源不足时,压缩部分不常用的内存页中的数据,释放更多空闲内存。比将内存数据换出到磁盘效率更快。
05 大页:每个内存页对应TLB中一个缓存项
优点:
- 有效缓解TLB缓存项不够用的情况
- 提高TLB命中率
- 减少页表级数,提升页表查询效率
缺点:
- 程序未使用整个大页造成物理资源浪费
- 增加操作系统管理内存的复杂度
适用情况:
- 应用程序对内存需求量大
- 高并发时,虽然每个并发请求占用内存量不大,但是总量大
物理内存的分配和管理
01 目标和评价维度
- 外部碎片:频繁的分配与回收物理页会导致大量的、连续且小的页面块夹杂在已分配的页面中间,就会产生外部碎片。
- 内部碎片:分配的内存大于实际使用的内存,这种被浪费的内存空间是内部碎片。
物理内存分配器的目标:降低分配延迟,节约cpu资源。
02 伙伴系统: 内存被分成含有很多页面的大块, 每一块都是2个页面大小的方幂. 如果找不到想要的块, 一个大块会被分成两部分, 这两部分彼此就成为伙伴. 其中一半被用来分配, 而另一半则空闲. 这些块在以后分配的过程中会继续被二分直至产生一个所需大小的块。 当一个块被最终释放时, 其伙伴将被检测出来, 如果伙伴也空闲则合并两者。
有效缓解外部碎片。
03 SLAB分配器:伙伴系统最小的分配单位是一个物理页4KB,SLAB用于更小内存的分配。
SLUB分配器是为了满足操作系统频繁的分配小对象的的需求,依赖于伙伴系统进行物理页分配,并将物理页分成更小的固定大小的内存块进行管理。对于每一种块大小,SLUB都会使用独立的内存资源池进行分配。
有效避免外部碎片,分配速度很快;通过设置不同大小的内存资源池,尽可能减少内部碎片导致的开销。