内存管理

The Bass Demon

Fri 11 . September

简介

这篇文章将会着重介绍内存寻址的不同方法。因为我没能全部亲自参与工作--,所以我将用这篇文章作为对不同技术的摼閿。首先,我将从范围为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)指定,如果想知道更多的有关知识,请参阅英特尔手册。

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

如果你忘记分页功能并且不认为需要或想要实现虚拟内存功能,你可以使用我在实模式部分中提到的任何方法。使用一个摳帐褂霉牡刂窋的指针的方法是一个傻瓜式并廉价的解决方法。这种方法也有一些问题,叫做撃诖娑磾和撃诖嬗成銲/O敗>蠖嗍鼴IOS都有选项,可以启动一个所谓的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位形式的都可以,但是要用到句柄表。不再使用全局描述表来寻址哪段范围的内存属于哪个应用程序。使用基地址指定起始页,并用界定描述符计算页数。当程序需要分配内存时,将得到一个描述符值,类似于内存句柄。

关于内存的管理实在是没有更多的话可说了,祝好运,并祝你做一个非常成功的OS!!