操作系统实验--30天自制操作系统第10天实验日志

一、实验主要内容

1、 内容1:内存管理

为了减少内存碎片,我们要编写一些以4kb为单位进行分配和释放的函数,把指定的内存按4kb单位向上舍入。
向下舍入:以某个单位向下舍入就是将不足一单位的的数字舍去,对二进制或者十六进制来说就是将后面几位变为0。可以通过与运算来获取结果。
例如以0x1000为单位向下舍入:i=i&0xfffff000
向上舍入:与向下舍入相反,它是将不足一单位的数据补齐一单位。所以对不是一个单位的整数倍来说,一个数向下舍入就是将其先向上舍入再加上一个单位数据。
例如以0x1000为单位向上舍入
在这里插入图片描述

或者:
在这里插入图片描述

逻辑是一样的,假如size是0x1000的整数倍,那么它加上小于0x1000的数字0xfff再向下舍入就是它本身,和它向上舍入的结果相同;假如size不是0x1000的整数倍,那么它加上0xfff后第四位肯定会进位,然后再向下取舍入到的结果肯定就是它向上舍入的结果。
在这里插入图片描述

这里策略类似于内存分页管理,只会分配给程序以页(4kb)为单位的内存,虽然会造成内部间隙,但这样可以减少内存的碎片化,减少外部间隙,使内存更加可用。

2、 内容2:叠加处理

能用于鼠标的叠加处理,也能直接适用于窗口的叠加,主要通过移动图层的方法实现鼠标指针的移动以及窗口的移动。
描述一个图层的结构体:
在这里插入图片描述

buf: 图层上描画内容的地址,图层的整体大小bxsize*bysize
(vx0,vy0):图层在画面上位置
Col_inv: 表示透明色号
Hight: 图层高度,但是它不是说真的高度,而是第几层的意思,理解这个很重要,高层的不会被低层的覆盖住。
Flags: 存放图层的各种设定信息
管理多个图层的结构体:
在这里插入图片描述

top最上面图层的高度,sheets0存放256个图层信息,sheets记忆地址变量:把sheets0里的图层按照高度进行升序排列,把地址写入sheets
所占空间:

在这里插入图片描述

图层管理初始化:
先申请以4kb为单位的图层管理结构体,用于后续的图层管理,初始化中最大高度设为-1表示还没有图层正在显示,同时将每个图层初始化为未使用
在这里插入图片描述

取得未使用的图层:
在这里插入图片描述

效果很简单,遍历所有的图层,找到一个未使用的,然后,将其高度初始化为-1,表示图层还为显示,然后返回即可,若没有未使用的图层返回-1表示申请失败.
设定图层的缓冲区大小以及透明色:
在这里插入图片描述

图层显示总要有数据吧,这里设定图层显示的图像信息,有图像数据和大小,透明色
设定图层高度的函数(比较长这里不贴了):
其代码逻辑为:
(1)若要设定的图层高度变高了,而且该图层一开始不是未显示的状态,则将该图层要到的高度到该图层原高度之间的图层全部向下移动一个高度空出目标高度,然后将图层放入目标高度中,若一开始处于未显示状态则将目标图层高度及以上的图层全部向上移动一个高度,空出目标高度。
(2)若要设定的图层高度变低了,而且该图层不是变到未显示的状态,则将该图层要到的高度到该图层原高度之间的图层全部向上移动一个高度空出目标高度,然后将图层放入目标高度中,若要移动到未显示状态则将目标图层高度以上的图层全部向下移动一个高度,占住出目标高度。
(3)最后刷新画面,刷新页面的函数如下:
刷新画面的函数:
原理很简单,从最低的图层开始向上绘制该图层在画面上的区域即可,其中图层中和透明色相同的颜色不会绘制,这个功能一般用于绘制不规则的图形(比如鼠标)
在这里插入图片描述

不改变图层的高度,只上下左右滑动的函数:
在这里插入图片描述

这个函数的应用情况就是,虽然该图层的位置变了,但是他的显示次序没变,意思就是就算更改后该图层的位置变高了,但是它还是能被height值比它高的图层掩盖住。
释放已经使用的涂层:
在这里插入图片描述

其实从这也能看出来,所谓的内存释放不是真的对内存进行了什么操作,而是不再占用这块内存,可以向这块内存写数据洗掉以前的数据。
改造入口函数:首先准备两个图层,分别是sht_back和sht_mouse,两个缓冲区buf_back和buf_mouse,用于描绘图形。在每次修改缓冲区之后,都需要进行图层刷新。
在这里插入图片描述

最终结果:
在这里插入图片描述

3、 内容3:提高叠加处理速度1

我们最开始鼠标一移动,就对整个画面进行刷新,但是其实我们对鼠标移动前后的共16162=512个像素进行描绘就行了。
在图层刷新的函数中,我们增加一个if语句,来实现其试用vx0~vy1指定所要刷新的范围。
在这里插入图片描述

这个函数只对以(vx0,vy0)为左上角、以(vx1,vy1)为右下角的长方形区域内进行刷新,而以前是对整个buf区域进行刷新。
在这里插入图片描述

这个函数首先记住移动前的显示位置,再设定新的显示位置,最后只要重新描绘移动前和移动后的地方就可以了。
在显示文字的时候,我们只需要刷新816字的个数的字节的像素,但是我们每次却刷新了64000个像素,所以要重新编写函数sheet_refresh。
在这里插入图片描述

最后对使用了这些函数的地方进行相应修改即可
效果:刷新速度变快

4、 内容4:提高叠加处理速度2

在原来的refresh函数中,是对图层的全部像素进行执行if语句,然后再判断是否写入,所以这次改良将for语句定在刷新范围之内。
在这里插入图片描述

改良之后,如果指定的范围大于缓存区的大小,就把它修正为缓存区的大小;如果指定的范围小于缓存区的大小,就只对指定范围的每个像素进行if判断,原来是对整个缓存区范围内的像素执行if语句。而且改良之后for循环的次数也减小了。
举几个例子;
在这里插入图片描述
在这里插入图片描述

像这两种情况就只会
刷新图层与刷新区域
重合的地方

二、遇到的问题及解决方法

1.描述问题1:这里想要编写一个鼠标可以控制窗口移动的效果代码时,如何表达鼠标一直按着窗口?

解答:这里要通过多个标志位进行处理,定义一个move_flag标志位表示鼠标是否处于持续点击中,和change_flag用于记录当鼠标持续点击时在窗口的相对位置,该move_flag标志位会在每一次运行程序时(在无限循环里),每一次都赋为0,而change_flag只会在其等于0时,将其赋值为1并记录鼠标在窗口的相对位置,当中断信息表示鼠标在窗口栏区域左键点击时,将move_flag赋值为1,这样一来只要我们在后面判断move_flag的值,只要move_flag=0我们就认为连续的点击中断了,将change_flag=0重新确定相对位置。

三、程序设计创新点

1、描述创新点1:新建一个窗口图层,实现点击右上角就关闭窗口

步骤很简单,首先我们要建立一个图层,如图先申请一个图层并申请图形数据的内存空间
在这里插入图片描述

然后对窗口进行绘制,并设置图层属性:
在这里插入图片描述

最后将图层移动到合适位置(wx=80,wy=80):
在这里插入图片描述

然后我们现在运行就能看到我们的图层了,不过现在单击右上角的黑色区域并没有效果
现在我们编写鼠标和按键交互的代码:
在这里插入图片描述

按下左键后,若鼠标位置在我们黑色按键的位置,则将窗口关闭,并改变此时窗口的状态(用于避免后续修改时持续刷新窗口)
最终效果:
在这里插入图片描述

2、描述创新点2:实现“桌面图标”,该图标具有类似于windows系统的鼠标放置图标上图标背景色加深,单机时颜色转为选中背景色,双击时打开窗口

先看看我们的具体需求有哪些
(1)鼠标放在按钮上时,按钮背景色会加深,移开时会变浅
(2)若鼠标在按钮上单击后,按钮背景色会到最深,移开时会变浅(颜色会变到和(1)颜色加深时一样(Windows中图标的选中状态))
(3)鼠标若在按钮上单击后,再离开按钮区域并在其他区域单击时,按钮颜色变回原来最浅的时候
(4)鼠标在按钮上双击时打开窗口
我们一个一个解决:
考虑到按键颜色会有两种背景色变化,这里我们定义一个deep_color来表示按键此时应该是何种背景颜色取值为0,1,2,然后我们分为鼠标在按键区域上和不在,鼠标在按键区域内点击和在区域外点击4种情况来分析
当鼠标放在按键上时:
因为我们鼠标会有一定连续的时间都会放在按键上,而这里我们的策略是将deep_color++,所以我们需要一个change_mutex标志位来保证只有第一次鼠标进入到按键区域时进行颜色加深的变化
在这里插入图片描述

当鼠标离开按键时:
同理鼠标离开时我们会对按键区域颜色做deep_color–,处理,所以要和前面一样保证只有在第一次离开按键区域时改变,同时要放开鼠标在按键区域时对颜色改变的权限(change_mutex=1)
在这里插入图片描述

当鼠标在区域内点击时:
这里为了区分双击和单击,我们在一次单击后开始计时(flag_count=1),然后改变按键颜色,并记录此时的颜色状态deep_color。
计时在无限循环的最开始处
在点击开启计时后如果在规定时间内再次检测到一次点击,我们就认为鼠标进行了双击,然后计时标志归0,计数值归0
在这里插入图片描述

当鼠标在区域外点击时:
将颜色变为最浅然后记录颜色深度deep_color即可
在这里插入图片描述

实际效果:
在这里插入图片描述

3、描述创新点3:实现鼠标对窗口的拖动

想要实现对窗口的拖动我们首先需要知道如何表达鼠标持续的按下这个状态
我们通过在无限循环的最开始将move_flag=0,然后在按下时重新将其赋值为1,后续进行该标志位的变化就可以知道鼠标是不是一直处于按下的状态了
在这里插入图片描述
在这里插入图片描述

在按下时检测,如果鼠标在窗口边框区域,我们将move_flag=1表示持续按下,然后如果这是第一次在边框按下,我们要记录鼠标和窗口的相对位置用于后面窗口跟鼠标位置的相对移动
在这里插入图片描述

在最后我们进行move_flag的判断,如果唯一表示现在还处于按下状态,然后我们计算出窗口此时应该处于的位置,最后进行移动
实际效果:
在这里插入图片描述

四、实验心得体会

这次实验主要引进了图层这一概念,主要思路就是用不同的buf将不同的图层存储下来,然后再通过一个结构体对不同图层的层次进行管理,还引进一个透明色的概念,基于它,我们可以实现移动鼠标而不让鼠标进行擦除。这与我前面实现的鼠标不被擦除方法类似,但在于背景色的方面,还是有所不同,最后我模仿Windows系统中鼠标与图标的交互做了一个启动窗口的按钮,并成功使用鼠标拖动了窗口,但这里的代码还写得比较死对于多个按钮或多个窗口的拖动关闭,几乎要多相应倍数的代码量,后续有机会的话看看能不能整合一个按钮类型的变量和相关操作来用于简化操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值