[转] 内存管理的方法


这篇文章将会着重介绍内存寻址的不同方法。因为我没能全部亲自参与工作,所以我将用这篇文章作为对不同技术的经验。首先,我将从范围为 00000000-000FFFFF 的 1M 内存的地址使用分配方式的描述开始。然后我将试图探讨 1MB-4GB 范围内存寻址的问题。

1M 内存

当我们说到 1M 内存时,我们将谈到实模式(real-mode),一种分段式内存模式,不具有 32 位寻址和内存分页的功能。

低端内存的特定区域都保留做特殊用途并必须进行正确处理。为了说明这一点,我将列出 1M 内存的映射的实例。

00000 - 003FF
IVT Interrupt Vector Table
(中断向量表)

00400 - 004FF
BDA BIOS Data Area
(基本输入输出数据区)

00500 - 00501
PRTSCR 1st byte is Print Screen Status BYTE
(第一字节是打印屏幕状态字节)

00501 - 9xxxx
OS OS specific
(操作系统专用区)

07C00 - 07CFF
BOOT Where Boot Sectors are loaded by the BIOS
(BIOS 装载引导扇区的区域)

9xxxx - 9FFFF
EBDA Extended BIOS Data Area,varies in size(at least 1KB)
(扩展 BIOS 数据区,大小不等,不小于1KB)

A0000 - AFFFF
VIDEO Used by the Video Adapter (Graphics Mode)
(用于彩色显示适配器)

B0000 - B7FFF
VIDEO Used by the Video Adapter (Monochrome)
(用于黑白显示适配器)

B8000 - BFFFF
VIDEO Used by the Video Adapter (Textmode)
(用于文本模式显示适配器)

C0000 - C7FFF
VIDEO Used by the Video BIOS
(用于显示适配器 BIOS)

C8000 - EFFFF
ROM May be used by adapter ROMS or as memory mapped I/O
(可用于适配器 ROM 或内存映射式 I/O)

F0000 - FFFFF
BIOS System BIOS,32K(starts at F8000) or 64K
(系统 BIOS,32k<从 F8000 开始>或者 64K)

内存的映射随系统不同而不同,但大部分都和上例相类似。最有可能出现不同的是范围为 C0000-FFFFF 的内存。

如果 EBDA 存在,那么它的尺寸大小将被在 BDA 内的偏移地址为 13H 处的一个 WORD 的变量指定,单位为 KB.操作系统能够使用的内存最多可达到这里所指定的数量,但使用这些内存的程序必须随程序提供共享这些内存的方法,否则将是无用的。有一些其他的程序可能会用到这些内存,如病毒和其他先于 OS 驻留内存的软件。或借助 ROM 或通过引导扇区。

下面是一些内存寻址的方法:

方法1:

维护一个类似于在 BDA[13] 处的指针。初始化将其指向一个段,其紧接于你的操作系统内核和驻留驱动程序所需段之上。然后无论何时你需要加载一个新程序/驱动程序/模块/等等,你只需增加指针到所需的内存量。然后将指针的前一个值和当前值赋给程序,以使之知道其所能使用的内存数量。

方法2:

将内存按照需要划分成块(block),并维护一个位于块头部的小数据结构,包含块状态信息。这是 DOS 使用的内存管理方法。优点是可以以任意的次序释放内存。缺点是内存碎片问题和新生成块的处理较复杂。

方法3a:

在内存的特定区装载一位图文件,其中每一位代表一个内存块的状态。你可以在“大块和小位图”和“小块和大位图”之间选择。选 1KB 为块单位是个好主意。与此相关的位图大小可使用期 640 比特,或 80 字节。当需要内存时,只需寻找一个数量够大的范围即可。显而易见,使用 16 字节大小的块将会更灵活,但是相应的需要一个更大的位图──5KB 或 5120 字节。这种方法需要操作系统或每个程序记住它所能使用的内存的范围,所以当其不在需要时,要正确释放内存。

方法3b:

与上述方法相似,但是每块使用 2 比特信息位。每块使用 2 比特,可以记录比使用/未使用更多的信息。你可以使用下例所示值:

0 - Free(simply unused,available memory).

1 - System Memory(OS and drivers).

2 - Program Memory(Code and Data for application programs).

3 - Reserved Memory(Can be used to specify ROMs and adapter memory).

方法4:

这个方法是对方法 3a 或方法 3b 的扩展。除了位图之外,让 OS 维护一个有关内存起/止对或类似信息的小表。无论何时程序需要内存,只需检测该表中的未使用对(0).

如你所见,如果这只是你的想象,那么你将不能设计出自己的内存管理器。

对于很多内存管理器,当你成功的分配内存时,将分配给你一个句柄(handle);当你成功的释放内存时,将分配给你的句柄也释放。这句柄可以是内存区/ 块的起始地址(方法 1 或方法 2 - DOS 模式)。对于方法 3a/3b,程序自身必须保存这些信息。句柄常用做指向内存信息表的索引(适于方法4)。

如果你决定使用位图/句柄方式,你需要使位图覆盖整个 1MB 范围内的内存,并且设置位来代替中断向量表(IVT),基本输入输出数据区(BDA),操作系统(OS),视频(VIDEO)和 ROM 区。这将防止内存管理器使用这些内存。

以上所说就是有关实模式内存管理的全部。简单的工作。接着我们转到 1MB 以上内存的管理问题,即 386+ 保护模式。

1MB-4GB 内存区域

你也许注意到,我已经很技巧地跳过过度的准保护模式的 286。原因是 286 使用和 8086 一样的 64K 段,但是包含 386 的选择器方案,允许你为段选择器指定 24 位的基地址。对于这种处理器最有用的内存管理技巧是我在前面提到的位图/句柄方案,虽然这样会有较大句柄表。但是对 286 处理器而言,处理起来绰绰有余…

对于 386 ,你将使用一种叫做分页功能的新模式。使用分页功能使处理器在逻辑线性地址和位于 MemR/MemW cycles 内的内存总线上的物理地址之间增加一个特殊层。处理器将内存空间分成 4KB 大小的块,称为简单页。新奔腾处理器也可以使用 2MB/4MB 页,但是现在我将忽略这种性能,因为我对其也不很熟悉。

使用分页功能的系统将具有一个或多个页目录,每个目录内含有指向分页表的指针,而分页表则依次指向 4KB 的简单页。页目录页的地址是由控制寄存器 3(CR3)指定,如果想知道更多的有关知识,请参阅英特尔手册。

这种模式用何种方法寻址?

如果你忘记分页功能并且不认为需要或想要实现虚拟内存功能,你可以使用我在实模式部分中提到的任何方法。使用一个刚使用过的地址的指针的方法是一个傻瓜式并廉价的解决方法。这种方法也有一些问题,叫做内存洞和内存映射 I/O。绝大多数 BIOS 都有选项,可以启动一个所谓的 15MB-16MB 大小的内存洞,用于适配器(多数为 PCI)。现在大多数视频卡也支持线性框架缓存。

现在我们再一次回顾位图/句柄方式。如果你设置一个位图,使其中的一位或两位对应于每个 4KB 页的状态,你可以初始设定其中的位来指定内存洞,适配器等状态。驻留在内存。然后你将需要一个存有地址对的大表,用于寻址已分配内存。好了,下面是一些我能想到的方法:

方法1:

设置一个的位图,其中的每一位代表每个 4KB 页。如果你有 128MB 的内存,则将被划分成 32768 个页,每个页使用位图中的一位。该位图接近一页!除此之外还包括一个表,表内含有若干 2 DWORD 地址对,描述起/止内存地址信息。所有被覆盖范围的位都将在位图中设置,当内存块释放是清除。

方法2:

同上,但是每页使用两位来指定状态。这将使存储的内存状态的信息更加细致。如上所建议的,可使用如下的三个值:

0 – Free (未用)
1 – System Memory (系统内存)
2 – Program Memory (程序内存)
3 – Reserved Memory (保留内存)

方法3:

使用我们熟知的位图,1 位或 2 位形式的都可以,但是要用到句柄表。不再使用全局描述表来寻址哪段范围的内存属于哪个应用程序。使用基地址指定起始页,并用界定描述符计算页数。当程序需要分配内存时,将得到一个描述符值,类似于内存句柄。

原文地址:http://topic.youkuaiyun.com/t/20010402/09/91389.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值