操作系统内存最全解析!!!( 八 )


保护位(Protection) 告诉我们哪一种访问是允许的,啥意思呢?最简单的表示形式是这个域只有一位,0 表示可读可写,1 表示的是只读 。
修改位(Modified) 和 访问位(Referenced) 会跟踪页面的使用情况 。当一个页面被写入时,硬件会自动的设置修改位 。修改位在页面重新分配页框时很有用 。如果一个页面已经被修改过(即它是 脏 的),则必须把它写回磁盘 。如果一个页面没有被修改过(即它是 干净的),那么重新分配时这个页框会被直接丢弃,因为磁盘上的副本仍然是有效的 。这个位有时也叫做 脏位(dirty bit),因为它反映了页面的状态 。
访问位(Referenced) 在页面被访问时被设置,不管是读还是写 。这个值能够帮助操作系统在发生缺页中断时选择要淘汰的页 。不再使用的页要比正在使用的页更适合被淘汰 。这个位在后面要讨论的页面置换算法中作用很大 。
最后一位用于禁止该页面被高速缓存,这个功能对于映射到设备寄存器还是内存中起到了关键作用 。通过这一位可以禁用高速缓存 。具有独立的 I/O 空间而不是用内存映射 I/O 的机器来说,并不需要这一位 。
在深入讨论下面问题之前,需要强调一下:虚拟内存本质上是用来创造一个地址空间的抽象,可以把它理解成为进程是对 CPU 的抽象,虚拟内存的实现,本质是将虚拟地址空间分解成页,并将每一项映射到物理内存的某个页框 。因为我们的重点是如何管理这个虚拟内存的抽象 。
加速分页过程到现在我们已经虚拟内存(virtual memory) 和 分页(paging) 的基础,现在我们可以把目光放在具体的实现上面了 。在任何带有分页的系统中,都会需要面临下面这两个主要问题:

  • 虚拟地址到物理地址的映射速度必须要快
  • 如果虚拟地址空间足够大,那么页表也会足够大
第一个问题是由于每次访问内存都需要进行虚拟地址到物理地址的映射,所有的指令最终都来自于内存,并且很多指令也会访问内存中的操作数 。
操作数:操作数是计算机指令中的一个组成部分,它规定了指令中进行数字运算的量。操作数指出指令执行的操作所需要数据的来源 。操作数是汇编指令的一个字段 。比如,MOV、ADD 等 。
因此,每条指令可能会多次访问页表,如果执行一条指令需要 1 ns,那么页表查询需要在 0.2 ns 之内完成,以避免映射成为一个主要性能瓶颈 。
第二个问题是所有的现代操作系统都会使用至少 32 位的虚拟地址,并且 64 位正在变得越来越普遍 。假设页大小为 4 KB,32 位的地址空间将近有 100 万页,而 64 位地址空间简直多到无法想象 。
对大而且快速的页映射的需要成为构建计算机的一个非常重要的约束 。就像上面页表中的图一样,每一个表项对应一个虚拟页面,虚拟页号作为索引 。在启动一个进程时,操作系统会把保存在内存中进程页表读副本放入寄存器中 。
最后一句话是不是不好理解?还记得页表是什么吗?它是虚拟地址到内存地址的映射页表 。页表是虚拟地址转换的关键组成部分,它是访问内存中数据所必需的 。在进程启动时,执行很多次虚拟地址到物理地址的转换,会把物理地址的副本从内存中读入到寄存器中,再执行这一转换过程 。
所以,在进程的运行过程中,不必再为页表而访问内存 。使用这种方法的优势是简单而且映射过程中不需要访问内存 。缺点是 页表太大时,代价高昂,而且每次上下文切换的时候都必须装载整个页表,这样会造成性能的降低 。鉴于此,我们讨论一下加速分页机制和处理大的虚拟地址空间的实现方案
转换检测缓冲区我们首先先来一起探讨一下加速分页的问题 。大部分优化方案都是从内存中的页表开始的 。这种设计对效率有着巨大的影响 。考虑一下,例如,假设一条 1 字节的指令要把一个寄存器中的数据复制到另一个寄存器 。在不分页的情况下,这条指令只访问一次内存,即从内存取出指令 。有了分页机制后,会因为要访问页表而需要更多的内存访问 。由于执行速度通常被 CPU 从内存中取指令和数据的速度所限制,这样的话,两次访问才能实现一次的访问效果,所以内存访问的性能会下降一半 。在这种情况下,根本不会采用分页机制 。
什么是 1 字节的指令?我们以 8085 微处理器为例来说明一下,在 8085 微处理中,一共有 3 种字节指令,它们分别是 1-byte(1 字节)、2-byte(2 字节)、3-byte(3 字节),我们分别来说一下


推荐阅读