操作系统基础知识2

虚拟内存技术
内存管理是计算机系统内存管理技术的一种,是对主存的一种抽象概念。为每个进程提供了一个一致的、私有的地址空间。

  1. 为每个进程提供一致的地址空间,简化内存管理
  2. 保护每个进程的地址空间不被其他进程破坏,隔离了其他进程的地址访问
  3. 将主存看做是磁盘空间的高速缓存,主存中只保存活动区域,并根据需要在磁盘与主存之间传送数据

物理寻址与虚拟寻址
计算机主存可以看做是M个连续字节组成的数组。每个字节都有唯一的物理地址,最简单的访问内存方式就是物理寻址。
虚拟寻址:CPU通过虚拟地址访问主存,在访问之前虚拟地址会被MMU翻译为一个物理地址,然后再访问主存。

**虚拟地址空间:**虚拟内存技术中虚拟地址一般是4G, 这是因为地址是四个字节32位的,能表示的地址是4G

一个进程用到的虚拟地址其实不到4G。而用到的内存区域,会通过页表映射到物理内存。所以每个进程都可以使用同样的虚拟内存地址而不冲突,因为它们的物理地址实际上是不同的,有独立的地址空间,

虚拟地址空间分配
操作系统基础知识2
虚拟地址空间大小不需要和物理地址空间一样大小。
linux内核将虚拟地址空间分为两部分: 用户进程空间以及内核进程空间,两者比例3:1

  1. 对CPU来说,目标存储器是物理内存,使用高速缓存做物理内存的缓存
  2. 对虚拟内存来说,目标存储器是磁盘空间,使用物理内存做磁盘缓存。

CPU高速缓存

  1. 将进程指令使用的虚拟地址通过MMU转化为物理地址
  2. 将物理地址映射到高速缓存的缓存行
  3. 高度缓存命中就返回
  4. 不命中,产生缓存缺失中断,从主存相应物理地址取值,并加载到高速缓存中。CPU从中断恢复,继续执行中断前的指令

虚拟内存页表
虚拟内存系统需要判断一个虚拟页是否已经被缓存在内存中。

  1. 根据虚拟地址找到页表项
  2. 判断页表内是否记录物理地址
  3. 有的话,返回物理地址,表示已经被缓存在内存中
  4. 否则,触发缺页异常,然后从主存中选择一个牺牲物理页,将虚拟页从磁盘加载到主存中。
  5. 然后继续执行之前的指令。

页表
每个进程都有一个页表,管理虚拟内存页与物理内存页的映射以及缓存状态。
页表加上MMU中的地址翻译硬件用于将虚拟地址翻译为物理地址。

页表的大小:
页表的大小等于页表项数* 页表项大小。 页表项数等于2^(地址位数-页内偏移位数)一般是2 ^ (32-12) = 2 ^ 20。

页表项的大小其实取决于内存块数,假设物理内存大小4G, 页大小4K, 同样也是 2^ 20,因此需要占用页表项的20个bit位,至少需要三个字节。
但是为了方便一个页存储整数个页表项,一般会将页表项大小变为4B
因此最终的页表大小为 2^20 * 4 B= 4M大小

多级页表:(节省空间)
采用一级页表的话,每个进程都需要4M大小的页表空间。
假设4G地址空间,使用4M大小的页,那么只需要10 ^ 3个页表项。每个页又细分为4KB大小的页,需要10 ^ 3个页表项指向子页。
也就是说一级页表项有1024项,每项对应一个二级页表, 4M地址空间。每个二级页表有1024项,每项对应实际4K页。 一级页表与二级页表自身大小都为4K。

页表项加载是按需加载,没有分配的虚拟页不需要建立页表项,一开始可以只建立一级页表项,二级页表项按需创建。
采用多级页表的地址翻译如下:
操作系统基础知识2
CPU翻译地址的过程:

  1. CPU页表基址寄存器,指向进程页表的基地址
  2. 根据实际的虚拟内存技术,将虚拟地址拆分为页内偏移以及虚拟页表号
  3. 页命中 缺页
  4. 将虚拟地址翻译成物理地址之后,根据高速缓存原理,将这个物理地址映射到高速缓存具体组、行、块中,找到实际数据。

快表(节省时间)
页表需要两次内存访问才能读取到数据,为了节省时间引入TLB。页表Cache,存储了当前最可能被访问的页表项,其内容是页表项的副本。

快表项由两部分组成 标识以及数据,标识存放虚地址一部分(判断是否命中),数据存放页号。
比如
操作系统基础知识2
标识存放 19-31 位, 数据存放 页号 13-31位。快表自身编号为 13-18位,64项
CPU根据虚拟地址找到快表号,然后比较标识判断命中,不命中时,去页表寻找物理页号,然后将页表项加载到TLB中。

全相连-直接匹配-组相连

  1. 全相连一个TLB表项可以与任意页表项关联 (空间利用率高,但匹配需要遍历)
  2. 直接匹配每个线性地址通过模运算找到唯一TLB表项(命空间利用率低,冲突率高)
  3. 组相连 将TLB表项分组,每个线性地址块对应的是一个组。地址转换的时候,计算线性地址块对应的组号,然后这个组内进行顺序比对

内存映射机制
虚拟内存的目标存储器是磁盘,初始化虚拟内存区域的内容时,会将虚拟内存区域与一个磁盘文件对象对应,这叫内存映射

由于内存映射机制,一个磁盘对象可以被多个进程共享访问,也可以被私有访问。共享访问,进程修改会影响其他进程。私有访问,写时会复制一个新的对象,然后修改。

fork函数内容:

创建一个带有独立地址空间的新进程,内核为新进程创分配资源,例如存储数据以及代码空间,分配唯一PID,将当前进程的页表也拷贝给新进程。将原来进程所有值赋值到新的进程,之后的代码也拷贝到新进程。
两个进程共享同样区域,包含**共享的内存映射以及私有内存映射。**一般来说都是私有内存映射,写时拷贝,为新的进程维护独立虚拟地址空间