Skip to content

Commit

Permalink
finish 10.9.5
Browse files Browse the repository at this point in the history
  • Loading branch information
liuchanglin committed Feb 20, 2020
1 parent 961cdda commit eaf5beb
Showing 1 changed file with 40 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -663,4 +663,43 @@ SLOB分配器用于有内存限制的系统,如嵌入式系统。SLOB(代表
但是,外部页表否定了反向页表的功能?由于只有在发生分页错误是才会引用这些页表,因此这些页表并不需要很快,相反它们自己会在需要时执行page in和page out。不幸的是,当内存管理在外部页表上处理一个分页错误时,它需要在后端存储中定位虚拟分页的位置,这时该分页错误可能会导致虚拟内存管理器生成另外一个分页错误。内核需要谨慎处理这种特殊情况,并推迟分页查找过程。
#### 10.9.5 Program Structure
#### 10.9.5 Program Structure
按需分页旨在对用户程序透明,在很多场景下,用于完全不会感知到内存的分页特性。然而在其他场景中,如果用户能够感知到底层的按需分页,就可以提高系统性能。
下面看一个人造的但内容丰富的例子。假设,分页大小为128个字。一个C程序的功能是将128*128的数组初始化为0,代码如下:
```
int i, j;
int[128][128] data;
for (j = 0; j < 128; j++) //数据
for (i = 0; i < 128; i++) //行
data[i][j] = 0;
```
注意数组以主行的方式保存,即数组的存储为data\[0][0], data\[0][1], · · ·, data\[0][127], data\[1][0], data\[1][1], · · ·,data\[127][127]。对于一个128个字的分页,每行等于一个分页。因此,上面的代码将每一页中的一个字归零,然后处理下一个分页,等等。如果操作系统给整个程序分配的内存少于128个帧,那么会产生128 × 128 = 16,384个分页错误。
相反,假设我们将代码修改为:
```
int i, j;
int[128][128] data;
for (i = 0; i < 128; i++) //行
for (j = 0; j < 128; j++) //数据
data[i][j] = 0;
```
这样在开始处理下一个分页前会将初始化当前分页中的所有字,将分页错误减少到128个。
谨慎选择数据结构和编程结构可以增加程序的局部(locality)并降低分页错误率以及工作集中的分页数。例如,如果每次都能访问一个栈的顶部,则说明这个栈有良好的局部性。相反,哈希表则用以分散引用,会导致不好的局部性。当然,局部的引用只是衡量使用数据结构效率的标准之一。其他比较重要的衡量因素包括,查找速度,内存引用总数,以及涉及的分页数。
在稍后的阶段中,编译器和加载器会对分页产生重大影响。独立的代码和数据生成的可重入代码意味着该代码分页 是只读的且永远不能被修改。干净的分页可以直接被替换而无需执行page out。加载器可以避免跨分页边界执行例程,将每个例程的工作保持在一个分页中。
如果多个例程相互多次调用,可以将其打包到一个分页中。这种打包是运筹学的箱装问题的一种变体:尝试将不同大小的段打包为一个固定大小的分页,这样就可以减小内存引用的分页。这种办法对大的分页非常有用。
#### 10.9.6 I/O Interlock and Page Locking

0 comments on commit eaf5beb

Please sign in to comment.