操作系统实验日志10
第10天:叠加处理
30天自制操作系统第10天
一、实验主要内容
1、 内容1:内存管理
为了减少内存碎片,我们要编写一些以4kb为单位进行分配和释放的函数,把指定的内存按4kb单位向上舍入。
-
向下舍入:以某个单位向下舍入就是将不足一单位的的数字舍去,对二进制或者十六进制来说就是将后面几位变为0。可以通过与运算来获取结果。
例如以0x1000为单位向下舍入:i=i&0xfffff000
-
向上舍入:与向下舍入相反,它是将不足一单位的数据补齐一单位。所以对不是一个单位的整数倍来说,一个数向下舍入就是将其先向上舍入再加上一个单位数据。
例如以0x1000为单位向上舍入:
还有一种方法:
逻辑是一样的,假如size是0x1000的整数倍,那么它加上小于0x1000的数字0xfff再向下舍入就是它本身,和它向上舍入的结果相同;假如size不是0x1000的整数倍,那么它加上0xfff后第四位肯定会进位,然后再向下取舍入到的结果肯定就是它向上舍入的结果。
PS:只有二进制数或者十六进制数可以通过与操作来向上或者向下取整,十进制数就只能通过我上面所说的逻辑通过除法进行运算,但是除法肯定要比与操作慢很多。
个人理解这种策略类似于内存分页管理,只会分配给程序以页(4kb)为单位的内存,短期来看浪费空间,但是长远来看,这样可以减少内存的碎片化,使内存更加可用。
2、 内容2:叠加处理
能用于鼠标的叠加处理,也能直接适用于窗口的叠加,主要通过移动图层的方法实现鼠标指针的移动以及窗口的移动。
描述一个图层的结构体:
buf: 图层上描画内容的地址,图层的整体大小bxsize*bysize
(vx0,vy0):图层在画面上位置
Col_inv: 表示透明色号
Hight: 图层高度,但是它不是说真的高度,而是第几层的意思,理解这个很重要,高层的不会被低层的覆盖住。
Flags: 存放图层的各种设定信息
管理多个图层的结构体:
top最上面图层的高度
sheets0存放256个图层信息
sheets记忆地址变量:把sheets0里的图层按照高度进行升序排列,把地址写入sheets
所占空间:
图层管理初始化:
取得未使用的图层:
设定图层的缓冲区大小以及透明色:
设定图层高度的函数(代码就不贴了,书上都有备注,写一下该函数的逻辑):
首先通过代码,可以看出来sheets[ ]排序的逻辑是,sheets[ i]表示排序为第i高的高度为i的图层。
设图层新设定的图层高度用new表示,该图层以前的高度用old表示。
首先进行修正:
而且可以看到,只有在该函数中有对sheets[]的操作,并且我们没有对该结构体数组进行初始化,没有数据的时候,我们就是在不断的赋空值,也只在该函数中,我们对top值进行修改。
刷新画面的函数:
不改变图层的高度,只上下左右滑动的函数:
这个函数的应用情况就是,虽然该图层的位置变了,但是他的显示次序没变,意思就是就算更改后该图层的位置变高了,但是它还是能被height值比它高的图层掩盖住。
释放已经使用的涂层:
其实从这也能看出来,所谓的内存释放不是真的对内存进行了什么操作,而是不再占用这块内存,可以向这块内存写数据冲掉以前的数据。
改造入口函数:
①对图层管理器进行初始化,此时top值为-1,其他图层都初始化为未使用。
②分别为背景和鼠标申请图层,并初始化为隐藏。
③分别为背景和鼠标的属性进行设置,背景图层颜色的存储区为buf_back,大小为整个屏幕,无透明色所以设值为-1,鼠标图层颜色的存储区为buf_mouse,大小为16*16,需透明的色号为99,和鼠标初始化中的背景色相同,所以这样就不会显示鼠标的背景了。
④原来的屏幕初始化函数是将初始化的屏幕颜色信息直接写入VRAM,现在是写入buf_back先储存下来。
⑤将背景的起始位置设为(0,0)。
⑥先将背景置为0层,这之前top值为-1,所以最高就是0;鼠标置为1层,这之前top值为0,所以最高就是1。
⑦原来也是直接写入VRAM中,现在是写入buf_back先储存下来,然后通过刷新函数显示出来。
3、 内容3:提高叠加处理速度1
我们最开始鼠标一移动,就对整个画面进行刷新,但是其实我们对鼠标移动前后的共16162=512个像素进行描绘就行了。
这个函数只对以(vx0,vy0)为左上角、以(vx1,vy1)为右下角的长方形区域内进行刷新,而以前是对整个buf区域进行刷新。
这个函数首先记住移动前的显示位置,再设定新的显示位置,最后只要重新描绘移动前和移动后的地方就可以了。
在显示文字的时候,我们只需要刷新816字的个数的字节的像素,但是我们每次却刷新了64000个像素,所以要重新编写函数sheet_refresh。
改造对应的up_down函数:
改写入口函数:需要更改四个地方
效果:刷新速度变快
4、 内容4:提高叠加处理速度2
在原来的refresh函数中,是对图层的全部像素进行执行if语句,然后再判断是否写入,所以这次改良将for语句定在刷新范围之内。
改良之后,如果指定的范围大于缓存区的大小,就把它修正为缓存区的大小;如果指定的范围小于缓存区的大小,就只对指定范围的每个像素进行if判断,原来是对整个缓存区范围内的像素执行if语句。而且改良之后for循环的次数也减小了。
举几个例子;
二、遇到的问题及解决方法
1.描述问题1:无
三、程序设计创新点
1、描述创新点1: 新建一个窗口图层,实现点击x就关闭,点击扩大就扩大,点击缩小就缩小的功能。
①新建两个图层,一个图层用来表示缩小版的窗口,另一个图层表示放大后的窗口。
②对图层的缓冲区进行初始化
黄色框里面是在图层管理器中申请两个图层;红色框中是为两个图层的缓冲区申请内存;蓝色框里面是对两个图层缓冲区的大小、透明色进行初始化。
③绘制两个图层
④对每个图层的显示位置以及层次进行设置。
小窗口的位置在(80,72)处,大窗口的位置在(0,0)处,初始时,只显示小窗口,于是将其高度设为1。
⑤在获取鼠标的状态(按键情况以及位置)后,对窗口进行更改。
⑥changesmallwin函数,只有当小窗口显示出来的时候,该函数才起作用
⑦changemaxwin函数,只有当大窗口显示出来的时候,该函数才起作用:
效果图展示:
四、实验心得体会
这次实验主要引进了图层这一概念,主要思路就是用不同的buf将不同的图层存储下来,然后再通过一个结构体对不同图层的层次进行管理,还引进一个透明色的概念,基于它,我们可以实现移动鼠标而不让鼠标进行擦除,其实和我前两天的创新的思路也差不多,我觉得比较难的地方就是要严谨的把各个函数以及各个变量组织起来,还有就是在做更改的时候又要将没处都考虑到,然后这个实验剩下的部分就是讲如何可以让我们的程序变快,主要是在代码的角度,比如减少不必要的循坏啊判断啊来让我们的程序变得更快。