首页 > 解决方案 > 在操作系统中使用分页方法如何证明其开销是合理的?

问题描述

所以我正在阅读有关操作系统中的分页。使用分页作为内存管理方法的最大优点之一(我遇到过)是它解决了外部碎片问题(在操作内存和存储中)并允许进程在非操作内存中分配连续方式。但是要实现分页,我们需要跟上并搜索可能有大量条目(在某些情况下为数百万)的页表。而且我想这样做会产生很大的开销(无论是时间还是空间)。

我不明白的是,为什么我们不能每次将程序加载到操作内存中时将其划分为任意数量的段。我们可以将其划分为每个段“填补一个洞”如果需要,可以操作内存,从而解决外部碎片问题。显然,程序可以以非连续方式加载,我们只需要存储每个段(上限和下限)2个地址,也许还有一些段表来保存上订单。

引用我正在阅读的书(操作系统概念 - Abraham Silberschatz,Peter Baer Galvin,Greg Gagne,第 9 版):“由于它优于早期方法的优势,各种形式的分页在大多数操作系统中使用,从那些通过那些用于智能手机的大型机”。

我在这里错过了什么吗?使用分页如何证明其开销是合理的?我们真的需要跟踪每一页吗?在选择用于内存管理的正确方法时,是否还考虑了其​​他一些事情?

标签: memory-managementoperating-systempagingmemory-segmentation

解决方案


  1. 将程序划分为任意段。

它们不能完全是任意的。例如,我可能想为某些应用程序制作一个非常大的向量:

#define N 10000000
int v[N];
....
for (i = 0; i < N; i++) {
    v[i] = ...
}

编译器确实希望v看起来占据连续的内存位置。因此,您的分段器需要了解这些项目;但它变得更糟:

int *v;
v = malloc(sizeof(*v) * N);
for (i = 0; i < N; i++) {
   v[i] = ...;
}
  1. 证明开销的合理性:

现在您需要在运行时找到一大块物理上连续的 RAM,并且由于您没有重定位机制,因此您无法移动先前分配的块。这就是碎片问题;而且没有页面式的mmu,是很难解决的。

您可以通过将编译语言转换为伪解释语言来解决它;但有更多开销:编译:

a = v[i];

into:
    ld R0,R1+R2*4    ; + overhead of mmu.
or:
    mov R0, R1+R2*4
    call findseg
    ld R0, R0

在一般情况下,就 RAM 而言,开销约为 0.1%;举个具体的例子,A​​RM64 或 AMD64 架构上的 4k 页面需要 10 个字节。libc.so,在我的 linux 系统上,大约是 2M 的文本 + 40k 的数据;大多数程序只使用非常少量的这个。由于分页,只有使用的 libc 位需要占用内存。在具有 32 个进程的 64G 系统上,仅 libc 的节省就淹没了页表开销。

3:跟踪。有多种途径可以攻击这一点。一种是多种页面大小,大多数体系结构都支持。另一个是操作系统不必提供 MMU 的粒度。例如,在一个有 4k 页的系统上,它可以坚持只放弃 64K 块的内存。从而将管理开销减少了 16 倍,同时适度增加了粒度浪费。


推荐阅读