操作系统第九天:内存管理

一、实验主要内容
内容1:内存容量检查
进行内存管理之前,首先要做的事情,是搞清楚内存究竟有多大。
做法如下:
首先,暂时让486以后的CPU高速缓存功能无效。内存与CPU的距离比CPU内部元件远得多,因此在寄存器内部MOV要比从寄存器MOV到内存快得多。但另一方面,CPU却又必须要使用内存。
因此,CPU中加入了高速缓存(cache)。为了有效使用稀有的高速缓存,做出如下决定:每次访问内存,都要将所访问的地址和内容存到高速缓存中。往内存里写入数据也是一样,首先更新高速缓存的信息,然后再写入内存。
内存检查时,要往内存里随便写入一个值,然后马上读取,来检查读取的值与写入的值是否相等。如果内存连接正常,则写入的值能够记在内存里。如果没连接上,则读出的值肯定是乱七八糟的。方法很简单。但是,如果CPU里加上了缓存会怎么样呢?写入和读出的不是内存,而是缓存。所以,在内存检查时必须将内存设置为OFF。相关函数如下:
在这里插入图片描述
在这里插入图片描述

最初对EFLAGS进行的处理,是检查CPU是486以上还是386。如果是486以上,EFLAGS寄存器的第18位应该是所谓的AC标志位;如果CPU是386,那么就没有这个标志位,第18位一直是0。这里,我们有意识地把1写入到这一位,然后再读出EFLAGS的值,继而检查AC标志位是否仍为1。最后,将AC标志位重置为0。
运算符"~",它是取反运算符,将所有的位都反转
为了禁止缓存,需要对CRO寄存器的某一标志位进行操作。
在这里插入图片描述

这个函数,是内存检查处理的实现部分。它调查了从start地址到end地址的范围内,能够使用的内存的末尾地址。因为如果p不是指针的话,就不能指定地址去读取内存,所以先执行”p=i”。将这个值保存下来,试写0xaa55aa55,然后在内存中对其进行反转,检查结果是否正确,再检查能不能返回初始值,最后再返回初始值。如果不能回复到初始值,就终止调查,报告终止地址。
但是这样运行太慢,就修改了函数部分如下:
在这里插入图片描述

改变的内容是不是一个一个检查,每次增加1KB,同样通过p=i+0xffc的方法,让程序只检查末尾的4个字节。
之前根据模拟器的设定,应该内存是32MB的,但是运行之后:
在这里插入图片描述

下面就来找问题。
内容2:内存容量检查(2)
如果我们不用”make run”,而是用”make -r bootpack.nas”,就可以确定bootpack.c中memtest_sub被编译成什么样子。下面是编译语言和C的对比
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

大家会发现,编译后没有XOR,并且只剩for。但这并不是编译器的Bug,而是引位编译器太优秀了。它进行了最优化处理,因为它根本想不到我们会对没有内存的地方进行读写。如果更改编译选项,是可以停止最优化处理的,但是除了这里的其他地方还需要这个编译选项,所以我们决定memtest_sub还是用汇编写吧。
汇编部分如下,对应位置已用注释标注出来:
在这里插入图片描述

这次再编译运行之后,,就是32MB了。
内容3:挑战内存管理
内存管理的基础,一是内存分配,二是内存释放。要启动某个应用程序,内存管理程序就会给出一个能够自由使用的内存地址,这就是内存分配。另一方面,内存使用完了,现在要把内存归还给内存管理程序,这就是内存释放。
先假设有128MB的内存吧。也就是说,有0x08000000个字节。我们假设以4KB为单位进行管理。
首先创建一个32768字节的区域,通过向其中写入0或者1来标记哪里空着,哪里正在使用。
在这里插入图片描述

如果需要100KB,那么找到连续的25标记为0的地方即可。
在这里插入图片描述

找到连续标记为0的地方之后,暂时将之标记为”正在使用”,然后从j的值计算出对应的地址。这里是0x1000为单位,所以j放大0x1000倍即可。
释放即把原来对应的地方再换回0 即可。
除了这种管理方法之外,还有一种列表管理的方法,是把类似于”从xxx号地址开始的yyy字节的空间是空着的”de44的这种信息都列在表里。
在这里插入图片描述

大体就是这个样子。之所以有1000个free,是考虑到即使可用内存部分不连续,我们也能写入到这1000个free里。比如,如果需要100KB的空间,只要查看free的状况,从中找到100MB以上的可用空间就行了。
如果找到了可用内存空间,就将这一段信息从”可用内存空间管理表”中删除。这相当于给这一段内存贴上了”正在使用”的标签。
如果size变成0,那么就可以直接删除这一段可用信息。释放内存时要看一下这条信息能不能和相邻的可用信息连接到一起,可以的话就归纳为一条。
这种新方法的优点,首先就是占内存少,并且大块的内存的分配和释放时十分迅速,但是缺点也肯定是有的。
首先,管理程序变复杂了很多,特别是将可用信息归纳到一起的处理,变得相当复杂。还有一个缺点,当可用空间被搞的零零散散,不能归纳到一块儿时,会将1000条可用空间管理信息全部用完。
作者最后采用的做法是,“只要割舍掉的东西,以后还可以找回来,就暂时不去管它。”
创建程序如下:
在这里插入图片描述
在这里插入图片描述

在这里创建了4000组的空间管理结构体,管理空间大约是32KB。
Memman_init:初始化memman,设定为空。主要工作是将frees设为0。
Memman_total:用来计算可用内存的合计大小并返回。
Memman_alloc:分配指定大小的内存。
关于释放内存函数因为太长了,就不截图了。主要进行的操作就是我们之前说的,如果分配到某一块的size=0,就直接删除这一条。如果释放的内存可以和相邻的进行合并,就合并。
最后,将程序应用于Harimain
在这里插入图片描述

这里表示决定使用自0x003c0000开始的32KB,然后将现在不用的内存以0x1000个字节为单位注册到memman里面。最后显示出累计可用内存容量。
Make run 结果如下:
在这里插入图片描述

实验内容结束。
二、遇到的问题及解决方法
问题1:检查开头四个字节和末尾四个字节有什么区别?
这个问题我暂时还是没有想明白。可能末尾四个字节显得更有一块都有效的代表性?毕竟一般都是被仔细检查过的,那么下界更具有代表性一些,如果末尾四位不对的话,至少说明这一块是部分有效的,所以不可用,对的话应该就都可行。但是开头四位的话就不大行。
三、创新点
创新点一:
采用列表管理的方法,当可用空间被搞得零零散散,怎么都归纳不到一块儿时,会将1000条可用空间管理信息全部用完。所以可否通过判断想要新添加的地址信息和所在合适范围内的范围内的空间进行比较,如果更大的话,就将小的空间替换出来。这样我觉得可以使得空间不那么零散。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值