荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: zzt (我命由我不由天), 信区: Program
标 题: 解决内存瓶颈问题
发信站: BBS 荔园晨风站 (Sun May 23 16:54:05 1999), 转信
发信人: mayanyi (▓▓※中坚分子※▓), 信区: Program
标 题: 解决内存瓶颈问题
发信站: 网易虚拟社区 (Wed May 19 01:43:45 1999), 站内信件
解决内存瓶颈问题
发信人: wql.bbs@bbs.swjtu.edu.cn (晖), 信区: dos
标 题: 解决内存瓶颈问题
发信站: 锦城驿站 (Thu Jun 26 22:19:33 1997)
转信站: xmucs!sjtunews!swjtunews!swjtubbs
Origin: xnjd21.swjtu.edu.cn
上海交大BBS供稿
摘要:本文用面向对象的程序设计方法,实现了对扩展内存和扩充内存的管理,
从而能够以对用户透明的方式使用扩展内存和扩充内存,较好地解决大型软件中
的内存资源瓶颈。
一、问题的提出
由于面向对象化编程的动态链接的特点,用C++完成的DOS 程序往往代码比较
庞大,占用内存空间较多。而在程序运行过程中,分配大量内存存储数据是在所
难免的。故常规内存资源十分紧张。尤其在大型的软件运行过程中,一旦内存不
够使用,将大大影响软件的可靠性。因此,有必要在保证内存资源方面找出较好
的方案,提高软件的性能。
从当前的国内情况来看,大部分微机都配有 4 兆以上内存。 如果全部加以
利用,软件的内存资源基本上就可以解决了。在利用这部分内存的方案上,有以
下几种:
① 用 80286/80386 保护模式访问。
但这个方案无法被所有的编程人员接受。因为即使是优秀的DOS编程人员,
编写保护模式程序也是相当困难的。
② 用保护模式的接口产品 DOS扩展器。
当采用C++编程时,应用DOS扩展器接口跟直接用保护模式编程差不多同样困
难。所以这种方法也不利于一般编程人员。
③ 用覆盖技术。
假如我们要存放的数据远大于代码,用覆盖技术仍然无法解决。
因此,应该提出更好的方案来。
由EMS(Lotus-Intel-Microsoft Expanded Memory Specification)规范提供
的中断调用,可以用扩展内存模拟扩充内存,具有强大的功能,为利用扩展内存
提供了方便;同时,XMS扩展内存规范提供了更直接的调用途径, 不需占用上位
内存。但两种规范使用时仍然要处理许多细节。为此,笔者在开发应用程序的过
程中,建立了一个内存管理类,以相对透明的方式分配扩展内存并存储数据,并
具有以磁盘建立虚存的功能。
二、扩充内存管理类
扩充内存管理类提供了分配扩充内存、转储数据或建立文件缓冲区的功能。
//EMM( for EMS )结构(供移动内存块用)(操作对象包括常规内存和扩充内存)
struct ywEmsEmb
{
long count; //以字节计的要移动的区域长度
char source_mem_type; //源内存类型 0: 常规内存; 1: 扩充内存
unsigned source_handle; //源句柄(若为0,则对应的偏移量是常规内存的
段内偏移*)
unsigned source_offset; //源初始偏移(常规内存在段内,扩充内存在逻辑
页内)
union
{
unsigned source_seg; //源内存块常规内存初始段地址
unsigned source_page_num; //源内存块扩充内存逻辑页
};
char dest_mem_type; //目的内存类型 0: 常规内存; 1: 扩充内存
unsigned dest_handle; //目的句柄(若为0,则对应的偏移量是常规内存
的段内偏*)
unsigned dest_offset; //目的初始偏移(常规内存在段内,扩充内存在逻
辑页内)
union
{
unsigned dest_seg; //目的内存块常规内存初始段地址
unsigned dest_page_num; //目的内存块扩充内存逻辑页
};
};
class ywEmsMem //扩充内存类
{
private:
Boolean init_success; //析构函数初始化是否成功
int ems_handle; //本扩充内存对象句柄
int ems_pages; //本句柄所对应的页数
Boolean error_code; //最近一次操作的错误代码(含义及定义参考中
断 67H *)
long useful_size; //本句柄中的有效数据
long ems_point; //分配到的扩充内存块的内部指针;其值为本句
柄所对应
//扩充内存块中的偏移量
char far * ems_page_frame; //映射窗口段地址
public:
ywEmsMem(void); //产生未经初始化处理的ywEmsMem对象
ywEmsMem(int pages); //产生pages个页面大小的ywEmsMem对象
ywEmsMem(long * size);
/*产生*size字节大小的ywEmsMem对象应使size的大小为16K的整数倍
否则,将分配到大于申请空间的内存,即将size进位16K的整数倍分配*/
ywEmsMem(char * filename,long * size);
//产生一个与文件filename相关联的对象,其空间大于或等于文件大小
//并已把文件中内容读入其中
~ywEmsMem();
Boolean InitEms(void); //检测是否安装EMS驱动程序及硬件能否正常
工作
Boolean GetInitResult(void); //取得初始化结果(成功或不成功)
Boolean MallocEms(int pages); //分配页面
Boolean ReMallocEms(Handle handle, int pages); //重新分配页面
Boolean FreeEms(int handle); //释放句柄所对应的页面
Boolean MapEms( int Physical_page, int Logical_page);
//映射页面存储器
Boolean MoveEmsMem( const struct ywEmsEmb * emb); //移动内存块; em
b--移动操*
Boolean GetErrorCode(void); //取得最近一次操作的错误代码的内存
结构
int GetCurentPages(void); //取得本句柄所对应内存的大小(以页计
)
long GetCurentSize(void); //取得本句柄所对应内存的大小(以字节
计)
long GetUsefulSize(void); //取得本句柄所有效数据占用的内存的
大小
Boolean SetEmsPoint(long Pnt); //设置当前指针位置
Boolean SetEmsPages(int pages); //重新设置本句柄所对应的页数
Boolean SetEmsSize(long * size);//重新设置本句柄所对应的字节数
void SetEmsDataIvalue(void); //设置句柄中的所有内容无效并置内部
指针位置
long GetEmsPoint(void); //取得当前指针位置
Boolean Ems_CharOnPoint(char far * ch , char mode );
//从当前指针处读取(或写入)一个字节
//读(写)完数据后,指针自动移动一个字节位置
//当 mode = READCHAR时,写入;当mode = WRITECHAR时
,读出
Boolean Ems_CharOnOff( long offset, char far * ch , char mode );
//从偏移量为offset处读取(或写入)一个字节
//读(写)数据时,不影响当前的指针位置
//当 mode = READCHAR时,写入;当mode = WRITECHAR时
,读出
Boolean Buffer_Ems( char far * buffer, long size, char mode );
//从当前扩充内存内部指针处读取size大小的数据到缓
冲区
//或将缓冲区中size大小的数据写入到当前指针所在位
置
//mode = READCHAR: 读出; WRITECHAR: 写入
Boolean WriteEmsToFile(char * filename, char * mode, long size);
//将从当前指针位置开始的size字节数据写入文件
Boolean ReadFileToEms(char * filename,long * size );
//将文件filename中的内容读入扩展内存的指针所在处的连续
空间
Boolean UsefulEmsToFile(char * filename,char * mode);
//将本句柄所对应的EMS中的有效数据内容写入文件
Boolean AllEmsToFile(char * filename,char * mode);
//将本句柄所对应的EMS中的所有内容写入文件
};
三、主内存管理类
主内存管理类提供了同时管理扩充内存和扩展内存( 如其中之一不存在,不
影响系统运行)的功能。另外还具有只占用340字节常规内存就可将任意大小的屏
幕图像保存到扩展内存的功能。限于篇幅,此处略去扩展内存管理部分和保存图
像部分。
主内存在管理内存的最大特点是当扩充内存和扩展内存都耗尽时,能够自动
将存储后长时间没有使用的数据交换到磁盘上,满足当前分配的要求;当被交换
到硬盘的数据要用到时,又能够自动交换到内存。具体实现方法是:每当分配一
块内存后,主内存管理对象首先将被分配的内存句柄放入队尾;当内存不够时,
从队列的队首取出最早分配的句柄。若该句柄未加锁,就把该句柄所对应的全部
或部分数据交换到硬盘上;若该句柄已加锁,将该句柄号放入队尾,继续判断当
前队首的句柄对应的数据是否可交换,直到找到为止。 在这里还略去了建立
内存堆之后的内存表、存储块等结构。
--
m;31m※ 来源:.网易虚拟社区 http://club.netease.com.[FROM: 202.102.65.183]m
--
m;34m※ 转寄:.网易 BBS bbs.netease.com.[FROM: bbs.huizhou.gd.cn]m
..
--
日出东方,唯我不败;
天上地下,唯我独尊。
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.143]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店