首页 > 其他分享 >【读书笔记-《30天自制操作系统》-26】Day27

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

时间:2024-10-09 21:23:44浏览次数:3  
标签:26 task 读书笔记 int 30 应用程序 cons LDT tss

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

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这种格式的库很常用。通过引入库,我们可以减少生成的目标文件。

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

标签:26,task,读书笔记,int,30,应用程序,cons,LDT,tss
From: https://blog.csdn.net/Ocean1994/article/details/142754004

相关文章

  • 20222303 2024-2025-1 《网络与系统攻防技术》实验一实验报告
    1.实验内容在本周的学习中,重新回顾了栈和堆的概念,还学习了安全漏洞的相关概念,然后聚焦在其中的缓冲区溢出漏洞上,明白了缓冲区溢出的定义及发生的原理,并了解了缓冲区溢出发展历史上的一些经典攻击案例,收获颇丰。在本次的实验中,我掌握了反汇编与十六进制编程器相关知识,同时对NOP,......
  • ​基于智谱清言大模型的本地安装与使用(3070TI)
    大模型简介什么是大模型大模型的发展历程大模型的特点大模型的分类安装步骤硬件要求环境准备cuda安装conda安装python虚拟环境创建git-lfs安装模型文件下载依赖安装检查安装成功使用基本调用模型的微调多轮对话格式数据集格式配置文件......
  • [HY000][1267] Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8m
    问题描述:[HY000][1267]Illegalmixofcollations(utf8mb4_general_ci,IMPLICIT)and(utf8mb4_0900_ai_ci,IMPLICforoperation'='出现这种问题就是关联表的字符集不匹配1.查看数据库的字符集showvariableswhereVariable_namelike'collation%';结果:2.查看关联......
  • 【读书笔记·VLSI电路设计方法解密】问题3:在最新工艺下,数百万-千万门级电路设计的挑战
    在超深亚微米(90纳米及以下,本书成于2007年)环境下设计一个系统级芯片(数千万门及以上)是一项同时解决许多复杂且相互依赖问题的任务。所需的设计/实施/验证方法论是一个动态发展的过程,因为随着工艺技术的不断进步,所涉及的挑战也在不断变化。今天最突出的挑战如下:时序闭合。时序闭......
  • 30人小企业如何轻松地上云?
    企业上云已经成为一种趋势,但对于没有IT背景真的30人小公司,如何挑选到合适的云盘软件?其实我们可以从需求反推,重点关注以下6点即可:易用性:软件应该直观易用,无需复杂的IT知识即可快速上手。价格:考虑到成本,应选择性价比高的解决方案,避免过高的支出。安全性:数据安全至关重要,需......
  • D30【python 接口自动化学习】- python基础之输入输出与文件操作
    day30F-strings输出学习日期:20241007学习目标:输入输出与文件操作﹣-42F-strings-如何通过定义好的格式进行输出?学习笔记:F-strings介绍F-strings的计算功能F-strings宽度和精度调整练习#宽度为10个字符,不足补0print(f'{number:010}')#000123.456#指定类......
  • 2020_01_26
    使用FFmpeg转换媒体文件的快速指南(转)原文FFmpeg是用于快速更改AV文件的格式或质量,提取音频,创建GIF等的出色工具。图片学分:JenWikeHuger摄有许多开源工具可用于编辑,调整和将多媒体准确地转换为您所需的内容。诸如Audacity或Handbrake之类的工具非常出色,但是......
  • ELX304 – Electronic Systems
    ELX304–ElectronicSystemsIndividualCourseworkAssignmentDigitalDesignSUBMISSIONONLINEon13/10/2024viaCANVASIntroductionThiscourseworkexercisewillprovideyouwiththeopportunitytodemonstratetheskillsyouhavedevelopedthroughout......
  • MT1301-MT1310 码题集 (c 语言详解)
    MT1301·1的补码c语言代码实现#include<stdio.h>intmain(){longn=0;longb=0;scanf("%ld",&n);inti=0;//while(b<n){b=b*16+0xf;}printf("%ld",b-n);return......
  • leetcode926. 将字符串翻转到单调递增
    如果一个二进制字符串,是以一些 0(可能没有 0)后面跟着一些 1(也可能没有 1)的形式组成的,那么该字符串是 单调递增 的。给你一个二进制字符串 s,你可以将任何 0 翻转为 1 或者将 1 翻转为 0 。返回使 s 单调递增的最小翻转次数。示例1:输入:s="00110"输出:1......