- 第一点,需要特殊的硬件来进行比较,并且它必须要快,因为它会在每次内存引用时使用。第二点,使用 4 位密钥,只能同时存储 16 个程序在内存中(其中一个是操作系统)。
- 这是一个巧合。基地址寄存器为 16,384,是因为程序恰好加载在地址 16,384 处。它可以加载在任何位置。限制寄存器为 16,384,是因为程序包含 16,384 字节。它可以有任意长度。加载地址恰好与程序长度完全匹配纯属巧合。
- 几乎需要复制整个内存,这需要读取每个字并将其重写到不同的位置。读取 4 字节需要 4 纳秒,因此读取 1 字节需要 1 纳秒,并且将其写入需要额外 2 纳秒,总共每个字节压缩需要 2 纳秒。这是一个每秒 500,000,000 字节的速率。复制 4GB( 字节,大约 字节),计算机需要秒,大约为 859 毫秒。这个数字稍微悲观,因为如果内存底部有一个初始空洞为 k 字节,这 k 字节则不需要复制。然而,如果存在许多空洞和许多数据段,空洞将很小,因此 k 将很小,计算中的误差也将很小。
- First fit 需要 20MB、10MB 和 18MB。Best fit 需要 12MB、10MB 和 9MB。Worst fit 需要 20MB、18MB 和 15MB。Next fit 需要 20MB、18MB 和 9MB。
- 实际内存使用物理地址。这些是内存芯片对总线上的反应数字。虚拟地址是指一个进程地址空间的逻辑地址。因此,一个具有 32 位字长的机器可以生成最大为 4GB 的虚拟地址,无论机器的内存大小是高于还是低于 4GB。
-
(页号,偏移量)对于 4KB 的页面大小,是(4,3616),(8,0),(14,2656),对于 8KB 的页面大小,是(2,3616),(4, 0),(7, 2656)。
- (a) 8212,(b) 4100,(c) 24684。
- 他们建立了一个 MMU,并将其插入在 8086 和总线之间。因此,所有 8086 的物理地址作为虚拟地址输入到 MMU 中。然后 MMU 将其映射到实际物理地址,然后传递给总线。
- 需要一个能够将虚拟页面重新映射到物理页面的 MMU。此外,当引用当前未被映射的页面时,需要向操作系统发出陷阱,以便它可以获取该页面。
- 如果智能手机支持多程序运行,像 iPhone、Android 和 Windows 手机一样,那么就支持多个进程。如果一个进程分叉并且页面在父进程和子进程之间共享,写时复制是有意义的。智能手机比服务器小,但在逻辑上并没有太大差异。
- 对于这些大小,为了确保每次访问 X 的元素都会发生 TLB(转换后备缓冲)缺失,M 至少要为 4096。由于 N 只影响 X 被访问的次数,任何 N 的值都可以。2. M 仍然应至少为 4096,以确保每次访问 X 的元素都会发生 TLB 缺失。但现在 N 应大于 64K,以引发 TLB 抖动,即 X 应超过 256 KB。
- 所有进程的总虚拟地址空间为 nv,因此需要这么多存储空间来存放页面。然而,存储器中可能存在 r 量,因此所需的磁盘存储空间仅为 nv-r。实际上很少需要这么多空间,因为很少有 n 个进程实际运行,且更少有所有进程都需要达到最大允许的虚拟内存。
- 每 k 条指令发生一次页错误会给平均值增加额外的开销 μs,因此平均指令执行时间为 ns。
- 页表包含 个条目,即 524,288 个。加载页表需要 52 毫秒。若一个进程获得 100 毫秒,其中 52 毫秒用于加载页表,48 毫秒用于运行。因此,52% 的时间用于加载页表。
- 在这些情况下:1. 我们需要每个页面一个条目,即 =16×1024×1024 个条目,因为页面号字段有 48-12=36 位。 2. 指令地址在 TLB 中命中率达到 100%。直到程序移动到下一个数据页面之前,数据页面的命中率将保持 100%。由于一个 4 KB 的页面包含 1024 个长整数,所以每 1024 次数据引用将有一个 TLB 缺失和一个额外的内存访问。
- TLB 的命中概率为 0.99,页表的命中概率为 0.0099,页面错误的概率为 0.0001(即只有 10,000 次引用中的 1 次会导致页面错误)。因此,每次有效地址翻译的时间为:
注意,有效地址翻译时间相当高,因为它主要由页面替换时间主导,即使页面错误只发生在 10,000 次引用中的一次。
- 考虑以下情况:
(a) 多级页表通过其层次结构减少了需要存储在内存中的实际页表的数量。事实上,在一个具有大量指令和数据局部性的程序中,我们只需要顶层页表(一个页),一个指令页面和一个数据页面。
(b) 为每个三个页面字段分配 12 位。偏移字段需要 14 位来寻址 16 KB。这样,页面字段还剩下 24 位。由于每个条目为 4 字节,一个页面可以容纳 个页表条目,因此需要 12 位来索引一个页面。因此,为每个页面字段分配 12 位将能够寻址所有 个字节。
- 虚拟地址由(PT1,PT2,偏移量)更改为(PT1,PT2,PT3,偏移量)。但是虚拟地址仍然只使用 32 位。虚拟地址的位配置从(10,10,12)更改为(2,9,9,12)。
- 20 位被用于虚拟页号,剩余 12 位用于偏移量。这产生了一个 4KB 的页面。20 位的虚拟页意味着有 个页面。
- 对于一级页表,需要 或者 1M 个页面。因此,页表必须有 1M 个条目。对于二级分页,主页表有 1K 个条目,每个条目指向一个二级页表。其中只有两个被使用到。因此,总共只需要三个页表条目,一个在顶级表中,一个在每个低级表中。
- 代码和引用字符串如下
LOAD 6144,R0 1(I), 12(D)
PUSH R0 2(I), 15(D)
CALL 5120 2(I), 15(D)
JEQ 5152 10(I)
代码(I)表示指令引用,而(D)表示数据引用。
- 有效指令时间为 ,其中 h 是命中率。如果我们将这个公式等于 2 并解出 h ,我们可以发现 h 必须至少为 0.75。
- 关联存储器从本质上将一个密钥与多个寄存器的内容同时进行比较。对于每个寄存器,必须有一组比较器,用于将寄存器内容的每一位与待搜索的密钥进行比较。实现这样一个设备所需的门(或晶体管)数量是寄存器数量的线性函数,因此扩展设计会线性增加成本。
- 对于 8KB 的页面和 48 位的虚拟地址空间,虚拟页面的数量为 ,即 (约 340 亿)。
- 主存储器有 = 32,768 个页面。一个 32K 的哈希表的平均链长度为 1。为了使链长度小于 1,我们必须增加到下一个大小,即 65,536 个条目。将 32,768 个条目分散到 65,536 个表槽位,将会得到平均链长度为 0.5,这样可以确保快速查找。
- 除非是在编译时完全确定的程序,否则这可能是不可能的,除非是非常特殊且不太有用的情况。如果编译器收集有关调用过程代码中位置的信息,这些信息可以在链接时用于重新排列目标代码,使得过程位于调用代码附近。当然,对于从程序中的许多位置调用的过程,这并没有太大帮助。
- 在这种情况下,1. 每次引用都会出现页面错误,除非页面帧的数量是 512,即整个序列的长度。2. 如果有 500 个帧,则将页面 0-498 映射到固定帧,并只变化一个帧。
- FIFO 算法的页面帧如下:
LRU 算法的页面帧如下:
FIFO 算法产生 6 个页面错误;LRU 算法产生 7 个页面错误。
- 选择的第一个带有 0 位的页面是 D 。
- 计数器的值为
页面 0: 0110110
页面 1: 01001001
页面 2: 00110111
页面 3: 10001011
- 序列:0, 1, 2, 1, 2, 0, 3。在 LRU 算法中,页面 1 将被页面 3 替换。在 Clock 算法中,页面 1 将被替换,因为所有页面都将被标记,且指针指向页面 0。
- 页面的年龄为 2204-1213=991 。如果 ,页面肯定不在工作集中且最近没有被引用,因此会被驱逐。当 时情况不同。现在页面仍在工作集中(勉强),所以不会被移除。
- a) 对于每个设置了 R 位的页面,将时间戳设为 10 并清除所有 R 位。也可以将 (0,1) 的 R - M 条目改为 (0,0*)。因此,页面 1 和页面 2 的条目将改为:
b) 退出页面 3( R=0 且 M=0 )并加载页面 4:
- a) 属性为:(FIFO) 加载时间;(LRU) 最近的引用时间;(Optimal) 未来最近的引用时间。 b) 有标记算法和替换算法。标记算法为每个页面添加 a 部分给定的属性标签。替换算法将剔除标签值最小的页面。
- 寻道加旋转延迟为 10 毫秒。对于 2KB 的页面,传输时间约为 0.009766 毫秒,总共约为 10.009766 毫秒。加载 32 个这样的页面将需要约 320.21 毫秒。对于 4KB 的页面,传输时间增加一倍,约为 0.01953 毫秒,所以每个页面的总时间为 10.01953 毫秒。加载 16 个这样的页面将需要约 160.3125 毫秒。对于如此快速的硬盘来说,唯一重要的是减少传输次数(或将页面连续放置在硬盘上)。
- NRU 移除页面 2,FIFO 移除页面 3,LRU 移除页面 1,Second chance 移除页面 2。
- 共享页面会引起各种复杂问题和选项:
(a) 如果进程 B 永远不会访问共享页面,或者当页面再次被交换出时访问它,应延迟进行进程 B 的页表更新。不幸的是,在一般情况下,我们不知道进程 B 将来会做什么。
(b) 代价是这种懒惰的页面故障处理可能会导致更多的页面故障。每个页面故障的开销在确定这种策略是否更高效方面起着重要作用。(另外:这种代价与支持某些 UNIX fork 系统调用实现的写时复制策略类似。)
- 碎片 B,因为代码具有比碎片 A 更高的空间局部性。内循环每隔一个外循环迭代才会引起一个页面故障(总共只有 32 个页面故障)。【另外(碎片 A):由于一个帧是 128 个字,X 数组的一行占用半个页面(即 64 个字)。整个数组可以容纳 =16 个帧。代码的内循环按列顺序遍历 X 的连续行。因此,对 X[i][j] 的每隔一个引用将引起一个页面故障。总的页面故障数将为 =2,048】。
- 这肯定是可以做到的。
(a) 这种方法与在智能手机中使用闪存作为页面设备类似,不同之处是虚拟交换区是位于远程服务器上的 RAM。虚拟交换区的所有软件基础设施都必须被开发。
(b) 这种方法可能是值得的,需要注意的是,磁盘驱动器的访问时间在毫秒级别,而通过网络连接访问 RAM 的访问时间在微秒级别,前提是软件开销不会太高。但是这种方法可能只在服务器群中存在大量空闲 RAM 的情况下才有意义。还有一个问题是可靠性。由于 RAM 是易失性的,如果远程服务器崩溃,虚拟交换区将丢失。
- PDP - 1 分页鼓的优点是没有旋转延迟。这样每次写入内存时可以节省一半的旋转时间。
- 此程序有 8 页文本,5 页数据和 4 页堆栈。该程序不适合,因为它需要 17 个 4096 字节页面。使用 512 字节页面的情况不同。在这种情况下,文本为 64 页,数据为 33 页,堆栈为 31 页,总共为 128 个 512 字节页面,适合存放。小页面大小是可以的,但大页面大小就不行。
- 程序发生了 15000 次页面故障,每次页面故障使用了额外的 2 毫秒处理时间。因此,页面故障的开销总共为 30 秒。这意味着在使用的 60 秒中,有一半的时间用于页面故障开销,另一半用于运行程序。如果我们使用两倍的内存来运行程序,那么页面故障的数量减半,只有 15 秒的页面故障开销,因此总运行时间将为 45 秒。
- 如果程序无法修改,则该解决方案适用于程序。如果数据无法修改,则该解决方案适用于数据。然而,程序通常无法被修改,而数据几乎不可能无法被修改。如果二进制文件上的数据区被覆盖为更新的页面,下次启动程序时将无法获得原始数据。
- 指令可能跨越页面边界,导致需要两次缺页错误来获取指令。要获取的单词也可能跨越页面边界,导致另外两次缺页错误,总共四次。如果内存中的单词必须对齐,数据单词只会导致一次缺页错误,但在具有 4KB 页面的机器上,加载地址为 4094 处的 32 位单词的指令在某些机器上(包括 x86)是合法的。
- 当最后一个分配单元未被充分利用时,发生内部碎片。当两个分配单元之间有空间被浪费时,发生外部碎片。在分页系统中,在最后一页的浪费空间将导致内部碎片。在纯分段系统中,分段之间总会有一些空间浪费。这是由于外部碎片。
- 不可以。搜索键使用了段号和虚拟页号,因此可以在一次匹配中找到精确的页面。
- 结果:
地址 | 错误? | |
---|---|---|
(a) | (14, 3) | 无 (或 0xD3 或 1110 0011) |
(b) | 无 | 保护错误:写入读取/执行段 |
(c) | 无 | 页面错误 |
(d) | 无 | 保护错误:跳转到读/写段 |
- 当所有应用程序的内存需求可预知且可控制时,不需要普通的虚拟内存支持。一些例子包括智能卡、专用处理器(例如网络处理器)和嵌入式处理器。在这些情况下,我们应当始终考虑使用更多的真实内存。如果操作系统不需要支持虚拟内存,代码会更简单、更小。另一方面,虚拟内存的一些思想可能仍然能够有利地利用,尽管需要有不同的设计要求。例如,程序 / 线程的隔离可以使用闪存进行页面交换。
- 这个问题涉及虚拟机支持的一个方面。近期的尝试包括 Denali、Xen 和 VMware。关键问题是如何实现接近本机性能,即仿佛执行的操作系统独占了内存。问题在于如何快速切换到另一个操作系统,因此如何处理 TLB。通常情况下,您希望为每个内核分配一定数量的 TLB 条目,并确保每个内核在其适当的虚拟内存上下文中运行。但是,有时硬件(例如某些 Intel 架构)希望在不知道您的操作意图的情况下处理 TLB 缺失。因此,您需要在软件中处理 TLB 缺失,或者提供用于为 TLB 条目附加上下文 ID 的硬件支持。