【读书笔记-《30天自制操作系统》-26】Day27

news2024/10/8 21:02:05

本篇内容不多,主要是一些优化的工作。首先优化了应用程序,然后引入对应用程序的保护功能,最后引入库的概念。
在这里插入图片描述

1. 应用程序优化

首先来解决上一篇中遗留的一个bug:使用ncst命令运行的应用程序,按下Shift+F1或者点击x按钮都无法关闭。

分析上一篇新增的代码,没有发现问题,因此这个问题应该是之前就已经存在了。解决的方法也很简单,只需要增加以下的代码:

按下Shift+F1按钮:

if (i == 256 + 0x3b && key_shift != 0 && key_win != 0) {	/* Shift+F1 */
	task = key_win->task;
	if (task != 0 && task->tss.ss0 != 0) {
		cons_putstr0(task->cons, "\nBreak(key) :\n");
		io_cli();	
		task->tss.eax = (int) &(task->tss.esp0);
		task->tss.eip = (int) asm_end_app;
		io_sti();
		task_run(task, -1, 0); // 增加此行代码
	}
}

鼠标点击:

if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) {
	/* 点击「×」按钮 */
	if ((sht->flags & 0x10) != 0) {		
		task = sht->task;
		cons_putstr0(task->cons, "\nBreak(mouse) :\n");
		io_cli();	
		task->tss.eax = (int) &(task->tss.esp0);
		task->tss.eip = (int) asm_end_app;
		io_sti();
		task_run(task, -1, 0);// 增加此行代码
	} else {	
		task = sht->task;
		io_cli();
		fifo32_put(&task->fifo, 4);
		io_sti();
	}
}

增加的语句是用来将休眠的任务唤醒。

虽然我们已经增加了结束任务的处理,但如果任务一直处于休眠状态,还是无法执行这些处理,导致无法结束任务。因此我们需要将任务唤醒。

为什么之前没有发现这个问题呢?因为在有命令行窗口的情况下,命令行窗口会触发控制光标闪烁的定时器中断。中断超时,会向FIFO写入数据,这样任务被自动唤醒了。因此之前虽然看起来可以强制结束,实际上还是有一定的延时的,最大是0.5s。

这样修改之后,就可以通过按键或者鼠标点击来关闭窗口了。

现在还有一个问题,在应用程序处于运行过程中时,无法关闭对应的命令行窗口。这里我们需要做一些优化。

首先是主程序:

……
if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) 
{
	/* 点击「×」按钮 */
	if ((sht->flags & 0x10) != 0) {		
		task = sht->task;
		cons_putstr0(task->cons, "\nBreak(mouse) :\n");
		io_cli();
		task->tss.eax = (int) &(task->tss.esp0);
		task->tss.eip = (int) asm_end_app;
		io_sti();
		task_run(task, -1, 0);
	} else {	
		task = sht->task;
		sheet_updown(sht, -1);//修改1:暂时隐藏图层
		keywin_off(key_win);
		key_win = shtctl->sheets[shtctl->top - 1];
		keywin_on(key_win);
		io_cli();
		fifo32_put(&task->fifo, 4);
		io_sti();
	}
}
……
else if (2024 <= i && i <= 2279) 
{	// 修改2:只关闭命令行窗口
	sht2 = shtctl->sheets0 + (i - 2024);
	memman_free_4k(memman, (int) sht2->buf, 256 * 165);
	sheet_free(sht2);
}

这里主要是两点优化。首先是点击x按钮时将命令行窗口图层隐藏的操作。因为有时关闭命令行窗口需要消耗一定的时间,这时先将图层隐藏能让用户觉得响应及时;然后就是在从FIFO中接收到console.c发送的关闭窗口请求数据后所进行的处理,这里主要是释放命令行窗口的图层。
API中键盘输入的部分需要做如下修改:

else if (edx == 15) 
{
	for (;;) 
	{
		……
		if (i == 4) {	// 修改点:只关闭命令行窗口
			timer_cancel(cons->timer);
			io_cli();
			fifo32_put(sys_fifo, cons->sht - shtctl->sheets0 + 2024);	/* 2024~2279 */
			cons->sht = 0;
			io_sti();
		}
		……
	}
} 

等待键盘输入期间,如果FIFO中接收到4,表示收到了关闭命令行窗口的信号。此时取消定时器,发出清理图层的消息,然后将cons->sht置为0。

2. 应用程序保护

接下来是增加一些对应用程序的保护措施。首先看下面的代码:

[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "crack7.nas"]

		GLOBAL	_HariMain

[SECTION .text]

_HariMain:
		MOV		AX,1005*8
		MOV		DS,AX
		CMP		DWORD [DS:0x0004],'Hari'
		JNE		fin					; 不是应用程序,不执行任何操作

		MOV		ECX,[DS:0x0000]		; 读取应用程序数据段的大小
		MOV		AX,2005*8
		MOV		DS,AX

crackloop:							; 全部用123填充
		ADD		ECX,-1
		MOV		BYTE [DS:ECX],123
		CMP		ECX,0
		JNE		crackloop

fin:								; 结束
		MOV		EDX,4
		INT		0x40

打开命令行窗口,运行lines程序;然后打开一个新的命令行窗口,在新窗口中运行crack7,lines应用程序的运行就会产生异常,这是crack7程序攻击了lines程序。

crack7程序首先从1005号段中的第四个字节开始读取数据,判断是否为“Hari”。这里1005其实代表第一个打开的命令行窗口所对应的应用程序代码段编号。如果从中读出“Hari”,该应用程序正在运行的可能性很高,接下来就读取段开头的4个字节,即应用程序数据段的大小。随后切换到2005号段,将其中的内容全部用123覆盖,这样就造成了程序的异常。

那么如何阻止应用程序攻击其他的应用程序呢?CPU已经具备了解决方案,这就是LDT(Local Descriptor Table)。与GDT相比,LDT同样用于设置段,但LDT中段的设置只对某个应用程序有效。这样其他程序无法使用,也就无法搞破坏了。

LDT的内存地址是通过在GDT中创建LDT段来告知CPU的。在GDT中可以设置多个LDT,和TSS非常相似。

我们在头文件中添加用于设置LDT的段属性编号。

#define AR_LDT		0x0082
……
struct TASK {
	int sel, flags; 
	int level, priority;
	struct FIFO32 fifo;
	struct TSS32 tss;
	struct SEGMENT_DESCRIPTOR ldt[2];// 增加LDT
	struct CONSOLE *cons;
	int ds_base, cons_stack;
};

将LDT的编号写入tss.ldtr,则创建TSS时就在GDT中设置了LDT。

struct TASK *task_init(struct MEMMAN *memman)
{
	……
	for (i = 0; i < MAX_TASKS; i++) {
		taskctl->tasks0[i].flags = 0;
		taskctl->tasks0[i].sel = (TASK_GDT0 + i) * 8;
		// 设置ldtr
		taskctl->tasks0[i].tss.ldtr = (TASK_GDT0 + MAX_TASKS + i) * 8;
		set_segmdesc(gdt + TASK_GDT0 + i, 103, (int) &taskctl->tasks0[i].tss, AR_TSS32);
		// 设置GDT时设置LDT
		set_segmdesc(gdt + TASK_GDT0 + MAX_TASKS + i, 15, (int) taskctl->tasks0[i].ldt, AR_LDT);
	}
	……
}

struct TASK *task_alloc(void)
{
	……
	for (i = 0; i < MAX_TASKS; i++) {
		if (taskctl->tasks0[i].flags == 0) {
			……
			task->tss.fs = 0;
			task->tss.gs = 0;
			// 删除原来的task->tss.ldtr = 0;
			task->tss.iomap = 0x40000000;
			task->tss.ss0 = 0;
			return task;
		}
	}
	return 0;
}

最后再修改应用程序,使应用程序创建在LDT中。

int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
{
	……
	if (finfo != 0) {
		/* 找到文件的情况 */
		……
		if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {
		……
		// 在LDT中设置程序的代码段与数据段
		set_segmdesc(task->ldt + 0, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60);
		set_segmdesc(task->ldt + 1, segsiz - 1,      (int) q, AR_DATA32_RW + 0x60);
			for (i = 0; i < datsiz; i++) {
				q[esp + i] = p[dathrb + i];
			}
			start_app(0x1b, 0 * 8 + 4, esp, 1 * 8 + 4, &(task->tss.esp0));
			……
		} else {
			cons_putstr0(cons, ".hrb file format error.\n");
		}
		memman_free_4k(memman, (int) p, finfo->size);
		cons_newline(cons);
		return 1;
	}
	return 0;
}

在start_app中使用的段号为4(=0x8 + 4)和12(1x8 + 4),乘以8的部分和GDT一致,而加4的部分表示该段号不是GDT中的段号,而是LDT中的段号。

这样再重复上面的操作,会产生异常,应用程序得到了保护。

在这里插入图片描述

3. 库

本篇的最后,为了简化已经开发完成的程序,引入了库的概念。

将一个庞大的程序拆解成小的部分(函数),将各个部分再组成完整的程序,这种编程方式被称为“结构化编程”。这样编写好的程序还可以保存下来,应用于其他程序。

依据这种思想,将可以用于其他程序的部件组织起来,就构成了库。库的扩展名为.lib,可以将多个.obj文件打包成库。如下面的Makefile内容:

GOLIB    = $(TOOLPATH)golib00.exe 

apilib.lib : Makefile $(OBJS_API)
	$(GOLIB) $(OBJS_API) out:apilib.lib

最终可以得到apilib.lib这样一个文件。

我们不仅可以自己编写库,也可以使用别人开发好的库。把库分享给别人时,文件也是越少越好,因此.lib这种格式的库很常用。通过引入库,我们可以减少生成的目标文件。

下一篇内容是文件操作与文字显示,敬请期待。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2197234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hierarchical Cross-Modal Agent for Robotics Vision-and-Language Navigation

题目&#xff1a;用于视觉语言导航的层次化跨模态智能体 摘要 1. 问题背景和现有方法 VLN任务&#xff1a;这是一种复杂的任务&#xff0c;要求智能体基于视觉输入和自然语言指令进行导航。 现有方法的局限性&#xff1a;之前的工作大多将这个问题表示为离散的导航图&#x…

『网络游戏』登陆启动框架【05】

将上一章的加载界面隐藏 1.游戏启动逻辑 创建脚本GameRoot.cs &#xff08;该脚本为游戏入口&#xff0c;作用初始化游戏&#xff09; 创建脚本&#xff1a;ResSvc.cs &#xff08;&#xff09; 创建脚本&#xff1a;LoginSys.cs &#xff08;&#xff09; 编写脚本&a…

解析Vue源码中是如何进行模版编译的

模版编译 联系前文&#xff0c;讲了虚拟DOM的patch过程&#xff0c;而虚拟DOM的前提是先有VNode&#xff0c;那么VNode又是从哪里来的&#xff1f;接下来讲的模版编译便是&#xff1a;把用户写的模版进行编译&#xff0c;就会产生VNode。 在日常开发中&#xff0c;我们把写在…

Qt-目录和文件

1. 目录和文件 1.1 目录操作 QDir 类用来处理目录 常用方法&#xff1a; QDir(QString path) &#xff1a; 实例化 absolutePath() : 获取目录绝对路径 dirName() : 获取目录相对路径 exists(dirPath) : 判断目录是否存在 mkdir(QString dirPath) : 创建目录 rmdir(QStr…

经典5级流水线概述

抽象化的流水线结构&#xff1a; 流水线的基本概念 多个任务重叠&#xff08;并发/并行&#xff09;执行&#xff0c;但使用不同的资源流水线技术提高整个系统的吞吐率&#xff0c;不能缩短单个任务的执行时间其潜在的加速比&#xff1d;流水线的级数 流水线正常工作的基本条件…

使用YOLO11实例分割模型进行人物分割【附完整源码】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

开放式蓝牙耳机哪个品牌好用?五大口碑最好开放式耳机力荐!

长时间佩戴传统入耳式耳机有时可能会影响耳道健康&#xff0c;鉴于此&#xff0c;转而选择不入耳设计的开放式耳机就成了不少人的新倾向&#xff0c;它们有助于减少细菌滋生和耳道闷热的烦恼。为了帮助大家找到合适的选项&#xff0c;下面我将列举一些市面上口碑不错的开放式耳…

跨境电商怎么搭建网络环境?

跨境电商搭建网络环境是一项复杂但至关重要的任务&#xff0c;它涉及到多个层面的技术和服务。以下是构建高效、安全、可扩展的跨境电商网络环境的一些建议&#xff1a; 1. 选择合适的云服务提供商 可靠性与稳定性&#xff1a;选择知名且有良好口碑的云服务提供商&#xff0c;确…

MySql复习知识及扩展内容

DDL操作库和表 -- todo ------------操作库---------------------------------- -- 创建库 create database if not exists day10 charset utf8; create database if not exists day11 char set gbk; -- 使用库 use day10; -- 查询库 show databases ; -- 删除库 drop databas…

mybatisplus整合springboot3出错(springboot多模块开发)

1.mybatisplus版本太低或者maven导入没用如下的 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version></dependency>2.maven导入冲突了&#xf…

千万不要再用varchar类型来存ip地址了!

对于一个ip地址&#xff0c;比如“192.168.0.110”&#xff0c;由于存在“.”号&#xff0c;所以大部分人都会用varchar类型的字段来进行存储&#xff0c;但是大家有没有想过&#xff0c;对于这样一个字符串&#xff0c;每个字符占用一个字节&#xff0c;那么就需要占用13个字节…

使用ChatGPT高级学术应用SciSpace的技术快速精准的搜索文献论文

在学术研究领域,文献综述是非常重要的一个部分。它不仅是对已有研究的梳理和总结,更是对新研究方向的探索和定位。面对浩瀚的学术文献海洋,传统的检索方法往往显得力不从心,既耗时又低效。 随着ChatGPT技术的突破,我们终于可以摆脱这一束缚,迎来一种全新的、高效的文献检…

程序员 -买房历险记

快生日了&#xff0c;自己又又 涨了一岁 买房 真不是 一件简单的事。 一. 买房 三大核心问题 1.一手/二手 房 2.哪个城市买 3.哪个地方买 我调研的是 三四线城市&#xff08;俺的老家&#xff09; 二. 买房需要 花多少&#xff08;看得到/看不到&#xff09; 比如 4000元…

SEO(搜索引擎优化)指南

SEO&#xff08;Search Engine Optimization&#xff09;是通过优化网站内容、结构和外部链接&#xff0c;提升网页在搜索引擎结果中的排名&#xff0c;从而增加网站流量的过程。SEO 涉及多个层面&#xff0c;包括技术 SEO、内容优化、外部链接建设等。以下是 SEO 的核心优化策…

HTML图形

HTML图形 1. HTML5 Canvas2.HTML5 内联 SVG3.HTML 5 Canvas vs. SVG 1. HTML5 Canvas HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。画布是一个矩形区域&#xff0c;您可以控制其每一像素。canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。 1、创建…

『网络游戏』窗口基类【06】

创建脚本&#xff1a;WindowRoot.cs 编写脚本&#xff1a; 修改脚本&#xff1a;LoginWnd.cs 修改脚本&#xff1a;LoadingWnd.cs 修改脚本&#xff1a;ResSvc.cs 修改脚本&#xff1a;LoginSys.cs 运行项目 - 功能不变 本章结束

springboot整合mybatis案例

springboot通过整合mybatis来实现数据的呈现。 一、springInitializer创建项目 注意&#xff1a;不选择也可以&#xff0c;创建项目后在pom.xml配置文件中引入依赖 <!-- mybatis起步依赖--><dependency><groupId>org.mybatis</groupId><art…

帕金森患者必看:十大忌口食物清单,守护健康从饮食做起!

一、高脂肪肉类 忌口理由&#xff1a;高脂肪肉类如肥肉、五花肉等&#xff0c;含有大量饱和脂肪&#xff0c;长期摄入会增加心血管疾病风险&#xff0c;而心血管疾病是帕金森病患者常见的并发症之一。建议选择瘦肉、鱼类等低脂高蛋白的食物。 二、腌制及加工食品 忌口理由&a…

pnpm在monorepo架构下不能引用其他模块的问题

一、研究背景 monorepo架构项目目录结构&#xff1a; - common- index.ts- ... - main- index.ts- ... - web- vue-demo- ... pnpm在monorepo架构下使用以下命令 pnpm -F main add common # or pnpm --filter main add common 并不能在main/index.ts中使用common/index.ts…

23.第二阶段x86游戏实战2-背包遍历(OD卡死解决办法,背包数量基址)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…