《操作系统30天》-合川秀实-学习日志day10

一、内存管理(续)

Menmman_free函数不足:出现不连续的小段未使用空间,把man->frees耗尽

解决:以0x1000(4KB)字节为单位分配内存和释放内存

主要添加的部分是向上舍入。

在二进制中想把某位变0,只需要进行“与运算”,而十六进制是二进制的组合,同意进行与运算就可以。

向下舍入:0x12345678 & 0xfffff000=0x12345000	->	i = i & 0xfffff000
向上舍入:i= (i	& 0xfffff000) + 0x1000 -> 相当于向下舍入再加了一个单位,实际上是错的,比如以100为单位对300向上舍入变成400.
向上舍入正确做法是先判断后舍入:
	if ( ( i & 0xfff) != 0 ) 	{ i=( i& 0xfffff000) + 0x1000; }
向上舍入改进版:i= ( i + 0xfff ) & 0xfffff000 ;
转为十进制理解:若当前为300(单位为100),加上99之后变成399,向下舍入还是300,若是301,加99变成400,向下舍入变成400结果正确,可以这样类比。
十进制的向下舍入:i=i-(i%100)

二、叠加处理

为深入解决鼠标移动问题 -> 做一段适用于鼠标和窗口叠加处理的程序

  • 最上面的小图层用来描绘鼠标指针,最下面是桌面壁纸,中间是窗口的图层。

图层结构体:

管理多重图层信息结构体(最大图层数256):

  • Sheets的部分有32x256=8192大小(8KB),如果还要加其他就很大了,所以使用mamman_alloc_4k来分配内存。

  • Shtctl_init()函数是对内存的初始化,用sizeof(变量)函数来指定所占空间大小,里面每一个图层都标记未使用。下一个函数sheet_alloc是获取新生成的图层,可以理解为对256个图层的初始化(标记为使用),但是都没有显示在界面中(height= -1)。

sht = &ctl->sheets0[i];表示ctl->sheets0[i]的地址

设定图层的缓冲区大小和透明色的函数:

设定底板高度的函数:void sheet_updown(struct SHTCTL *ctl, struct SHEET *sht, int height)

刷新函数:根据高度显示图层,最高的放在最上面(用户视角)

Bx:对应显示图层的横坐标(0开始)

By:对应显示图层的纵坐标(0开始)

滑动函数:重新显示就好了

释放函数:全部设置为隐藏

最后的主函数:

void HariMain(void)
{
	……
	struct SHTCTL *shtctl;
	struct SHEET *sht_back, *sht_mouse;
	unsigned char *buf_back, buf_mouse[256];

	……
	init_palette();
	shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);		/*初始化屏幕内存*/
	sht_back  = sheet_alloc(shtctl);
	sht_mouse = sheet_alloc(shtctl[两个图层,一个是sht_back和sht_mouse分别表示大背景和鼠标的背景(后面定义为透明色)]);
	buf_back  = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);	/*内存分配*/
	sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 屏幕的图层,没有透明色 */
	sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99);
	init_screen8(buf_back, binfo->scrnx, binfo->scrny);
	init_mouse_cursor8(buf_mouse, 99);/*背景色号 99*/
	sheet_slide(shtctl, sht_back, 0, 0); /*绘制背景滑动*/
	mx = (binfo->scrnx - 16) / 2; /* 画面中央的坐标计算 */
	my = (binfo->scrny - 28 - 16) / 2;
	sheet_slide(shtctl, sht_mouse, mx, my); /*绘制鼠标滑动*/
	sheet_updown(shtctl, sht_back,  0);
	sheet_updown(shtctl, sht_mouse, 1);/*设置为背景图层,1为鼠标图层*/
	
	(显示函数)
	sheet_refresh(shtctl);

	for (;;) {
		io_cli();
		if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
			io_stihlt();
		} else {
			if (fifo8_status(&keyfifo) != 0) {
				(获取鼠标并显示)
				sheet_refresh(shtctl);
			} else if (fifo8_status(&mousefifo) != 0) {
				(显示鼠标)
sheet_slide(shtctl, sht_mouse, mx, my); 
/* sheet_refresh滑动显示 */
				}
			}
		}
	}
}

显示结果:

三、提高叠加处理速度

第二点已经实现鼠标图层的移动,但是速度太慢。根据上面的原理,只要鼠标一动就会对整个画面重新刷新,相当于重写64000个像素。

  • 第一次优化:重写鼠标移动前和移动后的像素2x256=512,sheet.c其他函数保持不变,只修改刷新函数:

增加一个sheet_refreshsub函数

函数与sheet_refresh相比唯一不同在于使用vx0-vy1指定的刷新范围。加了一个判断条件 if (vx0 <= vx && vx < vx1 && vy0 <= vy && vy < vy1),意思是在传入参数的指定范围内才能绘制,在sheet_refresh中实现调用:

先记住移动前的位置,再设置新的显示位置,重新绘制这两个地方。

修改之后,作者还解决了一个文字显示问题:每次显示文字都要重写64000个像素,这里可以调用refreshsub函数,重写sheet_refresh函数就可以了:刷新指定范围(缓冲区坐标)

改造updown:
sheet_refresh(ctl);变成下面形式:
sheet_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize, sht->vy0 + sht->bysize);
最后改写bootpack.c:
变更点四个:每次往buf_back(屏幕)中写入信息才进行sheet_refresh
sheet_refresh(shtctl, sht_back, 0, 0, binfo->scrnx, 48);	//初始化屏幕
sheet_refresh(shtctl, sht_back, 0, 16, 16, 32);			//刷新键盘
sheet_refresh(shtctl, sht_back, 32, 16, 32 + 15 * 8, 32);	//显示鼠标信息
sheet_refresh(shtctl, sht_back, 0, 0, 80, 16);			//显示坐标
最后显示同上,速度提高!

四、提高叠加处理速度

  • 按照refreshsub的思路,会有bysize*bxsize次进入判断语句。这种写法每次刷新都要重新判断一次全部的显示图层(sht_back),所以作者修改了for语句的循环范围,如图:

  • 第二次优化:sheet_refreshsub函数

第一层for循环在于遍历图层,从低到高显示,理解了这一步,这样下面的判断就很好理解了: for (h = 0; h <= ctl->top; h++)

改良关键在于,bx在for语句中并不是在0到bxsize之间循环,而是在bx0到bx1之间循环,bx0,bx1都是通过刷新范围倒推出来的一个相对坐标值。Vx0的坐标相当于bx中的哪个位置,把它当作bx0。

根据

得出公式:vx= sht->vx0+bx; -> bx=vx-sht->vx0;

代码解析:

bx0 = vx0 - sht->vx0;

by0 = vy0 - sht->vy0;

bx1 = vx1 - sht->vx0;

by1 = vy1 - sht->vy0;

通过上面公式推导出的四个坐标值,对应图(例子)为:

这样就基本理解书本上的那些图了

当h=1时,想要重复刷新鼠标的图层,就变成下面:

这个判断说明的是在左上角叠加的情况:bx1,by1变大要修正。

只有满足叠加范围内的才会重新绘制,只绘制这一部分(BX0,BY0)->(BX1,BY1),其他的不用绘制。运行结果不变,速度变快。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值