iOS-虚拟内存
虚拟内存是对内存的一个抽象。支持虚拟内存的CPU需要通过虚拟寻址的方式来引用内存中的数据。CPU加载一个虚拟地址,然后发送给MMU进行地址翻译,MMU借助页表来获得物理地址。
物理内存
物理内存指的是内存条上的内存,早期一个进程的数据是全部加载在物理内存上,CPU直接通过物理内存地址来访问进程数据。这种方式会产生以下几个问题:
-
内存不够用
:启动的应用过多,全部加载会导致内存条的空间不够用。当应用越来越大的时候,用户可能只用到部分功能,此时如果全部加载到内存,会导致内存占用浪费。 -
内存数据的安全问题
:通过访问物理地址,可以直接修改物理内存上的数据。
为了解决物理内存的这几个问题,CPU访问进程数据就不能直接通过物理内存地址,而是通过虚拟内存来间接访问。
虚拟内存
虚拟内存是计算机系统内存管理的一种技术,虚拟内存为每个进程提供了一个连续、私有的地址空间,它每个进程会认为自己在使用一块大的连续的内存。事实上,每个进程的内存散布在物理内存的不同区域。或者可能被调出到备份存储中(一般在硬盘)。当一个进程请求自己的内存,操作系统负责把程序生成的虚拟地址,映射到实际存储的物理内存上。操作系统在分页表中存储虚拟地址到物理地址的映射。
- 通过映射表对虚拟内存和物理内存进行映射,从而达到访问内存的目的。CPU的Memory Management Unit(MMU)硬件 进行虚拟内存和物理内存的映射。此操作由操作系统管理。
- 内存映射表,一个表16k(iOS),MacOS是4k,Linux也是4k。可通过终端输入PAGESIZE进行查看。输出为字节数。
- 缺页中断(Page Fault),当虚拟内存访问的数据不再内存时,操作系统会阻塞当前进程把需要访问的数据加载到物理内存上。当物理内存不足操作系统就会覆盖其他进程的内存段来存放当前需要访问的数据。不同操作系统有不同的算法来实现该机制。iOS在把数据加载到当前页的时候还需要签名校验,每一次缺页中断的时间时0.6-0.8(抖音团队测试的结果),0.1-1(来自Hank大佬的测试) 单位:ms(毫秒)。
- 无论是物理内存还是虚拟内存的管理都是以页为单位来进行管理的,并且一般情况下二者的尺寸保持一致。
- 操作系统为每个进程建立一张进程页表mmu,页表记录着虚拟内存页到物理内存页的映射关系以及相关的权限。并且页表是保存在物理内存页中的。因此所谓的虚拟内存分配其本质就是在页表中建立一个从虚拟内存页到物理内存页的映射关系而已。而所谓的remap就是将不同的虚拟页号映射到同一个物理页号而已。就如例子中进程1的第1页和第4页都是映射在同一个6号物理页中。
- 不同进程之间的不同虚拟页号可以映射到相同的物理页号。
- 操作系统还会维持一个全局物理页空闲信息表,用来记录当前未被分配的物理内存。这样一旦有进程需要分配虚拟内存空间时就从这个表中查找空闲的区域进行快速分配。
寻址
现代处理器使用的是一种称为 虚拟寻址(Virtual Addressing) 的寻址方式。使用虚拟寻址,CPU需要将虚拟地址翻译成物理地址,这样才能访问到真实的物理内存。 实际上完成虚拟地址转换为物理地址转换的硬件是 CPU 中含有一个被称为 内存管理单元(Memory Management Unit, MMU)的硬件。MMU 需要借助存放在内存中的页表来动态翻译虚拟地址,该页表由操作系统管理。
内存分页
虚拟内存管理器对虚拟内存地址,划分为大小统一的内存块,称为 内存页,处理器及其内存管理单元(MMU)维护一个页表,此页表是程序的逻辑地址对计算机RAM中的物理地址的映射。当程序代码访问内存中的地址时,MMU使用页表将指定的逻辑地址转换为实际的硬件内存地址。
系统将内存页分为三种状态。
活跃内存页(active pages)- 这种内存页已经被映射到物理内存中,而且近期被访问过,处于活跃状态。
非活跃内存页(inactive pages)- 这种内存页已经被映射到物理内存中,但是近期没有被访问过。
可用的内存页(free pages)- 没有关联到虚拟内存页的物理内存页集合。
当可用的内存页降低到一定的阀值时,系统就会采取低内存应对措施,在OSX中,系统会将非活跃内存页交换到硬盘上,而在iOS中,则会触发Memory Warning,如果你的App没有处理低内存警告并且还在后台占用太多内存,则有可能被杀掉。
VM Region
一个 VM Region 是指一段连续的内存页(在虚拟地址空间里),这些页拥有相同的属性(如读写权限、是否是 wired,也就是是否能被 page out)。举几个例子:
mapped file,即映射到磁盘的一个文件
__TEXT,r-x,多数为二进制
_DATA,rw-,为可读写数据
MALLOC(SIZE),顾名思义是 malloc 申请的内存
VM Object
每个 VM Region 对应一个数据结构,名为 VM Object。Object 会记录这个 Region 内存的属性