首页 > 其他分享 >一个操作系统的设计与实现——第13章 任务(四):任务回收

一个操作系统的设计与实现——第13章 任务(四):任务回收

时间:2023-11-12 09:55:05浏览次数:26  
标签:13 函数 队列 回收 任务 PDE 操作系统

在前面的两章中,我们的操作系统均不支持任务回收,所以任务不能退出。本章将要实现的是任务回收功能。

13.1 任务回收的原理

如果一个任务位于任务队列中,其就会被运行。所以,如果一个任务的运行已经结束,它就应该从任务队列中删除。

仅仅将任务从任务队列中删除是不够的,这是因为任务还持有一些内存没有释放,这包括以下两部分:

  1. 任务地址空间中的页。包括3特权级栈、任务的加载地址,以及任务在运行期间申请的内存(我们的操作系统不支持此操作)
  2. 任务加载时分配的3页(loadTaskPL0函数和loadTaskPL3函数的第一行代码)

回收这两部分内存都不是难事,但问题是,谁来回收这两部分内存?是内核,还是任务自己?

如果由内核负责回收,那么,想要回收任务地址空间中的页,就需要临时切换到任务的CR3(就像任务加载时那样)。这个方案是可行的,只是略显麻烦。感兴趣的读者可以自行尝试。

如果由任务负责回收,那么,任务地址空间中的页可以直接回收,不需要切换CR3。但内核空间中的3页如果也由任务回收的话,将导致任务的0特权级栈立即失效,而此时,任务的回收还没有彻底结束,必然存在至少一条需要使用0特权级栈的指令,如ret,这条指令一旦执行,就会引发页错误。所以,这个方案是不可行的。(这段描述可能会令读者感到困惑,读者不妨先跳过这段话,在实现了任务回收以后再行理解)。

综上,由任务回收任务地址空间中的页比较方便,而内核中的3页必须由内核回收。因此,可将任务的回收分为两部分:

  1. 任务负责回收任务地址空间中的页
  2. 内核负责回收任务加载时分配的3页

任务切换是基于任务队列进行的。同理,任务回收也可以基于一个队列进行,不妨称之为退出队列。任务退出时,需要先回收任务地址空间中的页,然后将TCB添加到退出队列。另一方面,内核需要定期查看退出队列,如果其中存在TCB,就将其取出,并回收这个任务的3页内存。

13.2 任务回收的实现

13.2.1 回收任务地址空间中的页

请看本章代码13/Memory.h

第11行,声明了deallocateTaskCR3函数。

接下来,请看本章代码13/Memory.hpp

deallocateTaskCR3函数是本章新增的函数,其用于回收任务地址空间中的页。页的回收从PDE开始,如果PDE的P位为0,就可以直接跳过这个PDE;如果PDE的P位为1,就需要进一步遍历其中的1024个PTE,如果PTE的P位为1,就需要回收PTE指向的页,最后,还要回收PDE指向的页。

第141行,循环768次,每次考察一个PDE。768个PDE对应的是3G的任务地址空间。

第143行,使用第8章中的公式取得PDE指针。

第145行,判断PDE的P位。

第147行,遍历当前PDE中的每一个PTE。

第149行,使用第8章中的公式取得PTE指针。

第151行,判断PTE的P位。

第153行,从物理地址位图中删除PTE指向的页。PTE带有页属性,需要去除后才是物理地址。由于任务马上就要被回收了,所以虚拟地址位图无需修改。

第157行,从物理地址位图中删除PDE指向的页。同样的,PDE带有页属性,需要去除后才是物理地址,且不需要修改虚拟地址位图。

13.2.2 回收任务加载时分配的页

请看本章代码13/Task.h

第19行,声明了外部链接的退出队列exitQueue

第25行,声明了deleteTask函数。

接下来,请看本章代码13/Task.hpp

第13行,定义了退出队列exitQueue

第51行,对退出队列进行初始化。

deleteTask函数是本章新增的函数,其用于回收任务加载时分配的3页。

任务加载时,使用的是allocateKernelPage(3)以分配连续的3页,且第一页被用于TCB。因此,回收任务时,可以从退出队列中取出一个TCB,然后使用deallocateKernelPage函数直接回收连续的3页。

第216行,循环直至退出队列为空。

第218行,从退出队列中取出一个TCB,然后回收连续的3页。

接下来,请看本章代码13/Kernel.c

第22行,在循环中不断调用deleteTask函数,从而定期回收退出的任务。

第24行,将CPU挂起,等待外中断的唤醒。

13.2.3 任务退出系统调用

请看本章代码13/Int.s

第9~10行,声明了外部链接的退出队列exitQueue,以及deallocateTaskCR3函数。

taskExit函数是本章新增的函数。这是一个系统调用,用于任务退出。

第162行,调用deallocateTaskCR3函数,回收任务地址空间中的页。

第164~165行,取得TCB地址。

第167~170行,将TCB添加到退出队列中。

第172~190行与时钟中断处理函数的后半部分,即第130~148行一致。用于从任务队列中取出一个TCB并切换到这个TCB。

第248行,保留系统调用号1给后续章节使用(读取键盘输入的系统调用)。

第249行,将taskExit函数安装到系统调用表中,其系统调用号为2。

13.2.4 任务的自动回收

现在,2号系统调用已经安装,任务应在退出时发起这个系统调用。即,任务的代码应当是这样:

int main()
{
    // ...

    __asm__ __volatile__(
        "int 0x30\n\t"
        :
        : "a"(2)
    );
}

然而,要求每个main函数都在最后加这样一段代码是不现实的。这段代码应在任务退出时自动执行,这就是_start存在的意义。_start是一个任务真正的入口,main函数是由_start调用的,因此,在调用main函数的前后,还能进行其他操作。

请看本章代码13/Start.s

第1行,将编译模式设定为32位。

第3行,声明外部链接的main函数。

第5行,将_start声明为外部链接的。

第7行,开始定义_start

第9行,调用main函数。

第11~12行,在main函数退出后,自动发起2号系统调用。

接下来,请看本章代码13/Makefile

第6行,编译Start.s

第9行,将Test.oStart.o共同链接。此时,不再需要-e main

现在,每个任务都需要与Start.o共同链接,以具备自动发起2号系统调用的能力。在实际的操作系统中,含有_start的库会被链接器自动使用,所以,用户无需显式的写出这个库。

13.3 测试

本章使用的测试任务是13/Test.c。现在,我们的操作系统有任务的自动回收功能了,所以,任务可以正常退出,不再需要无限循环了。

标签:13,函数,队列,回收,任务,PDE,操作系统
From: https://www.cnblogs.com/yingyulou/p/17825526.html

相关文章

  • 13. 罗马数字转整数
    目录题目法一、最笨的办法法二、找到一点规律的解法题目罗马数字包含以下七种字符:I(1),V(5),X(10),L(50),C(100),D(500)和M(1000)例如,罗马数字2写做 II ,即为两个并列的1。12写做 XII ,即为 X + II 。27写做  XXVII,即为 XX + V + II 。通常情况下,罗马数字中小的......
  • 20211316郭佳昊 《信息安全系统设计与实现(上)》 第十周学习总结
    一、任务要求[1]知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容(4分)我在学****知识点,请你以苏格拉底的方式对我进行提问,一次一个问题核心是要求GPT:请你以苏格拉底的方式对我进行提问然后GPT就会......
  • windows操作系统中如何将apache zookeeper安装为系统服务
    记录一下,网上有些资料是错的,prunsrv的参数要以--开头!一下载最新版的apachecommonsdaemonhttp://archive.apache.org/dist/commons/daemon/binaries/windows/commons-daemon-1.3.4-bin-windows.zip解压,复制两个exe文件到zk的bin目录下二编写服务停止脚本(启动脚本不用自己......
  • [题解] CF1327F AND Segments
    ANDSegments有\(m\)个限制\((l,r,x)\)。要计算满足以下条件的长度为\(n\)的序列\(a\)的数量:\(\foralli\in[1,n],0\lea_i<2^k\)。\(\foralli\in[1,m],a_{l_i}\operatorname{and}a_{l_i+1}\operatorname{and}\cdots\operatorname{and}a_{r......
  • 2023-2024-1-20231317 计算机基础与程序设计第七周学习总结
    这个作业属于哪个课程<班级的链接>(如2022-2023-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(如2022-2023-1计算机基础与程序设计第七周作业)这个作业的目标<《计算机科学概论第8章》《C语言程序设计第6章》>作业正文https://www.cnblogs.com/Ter......
  • 2023-2024-1 20231327《计算机基础与程序设计》第7周学习总结
    学期(2023-2024-1)学号(20231327)《计算机基础与程序设计》第7周学习总结作业信息课程<班级的链接>(2023-2024-1-计算机基础与程序设计)要求<作业要求的链接>(2023-2024-1计算机基础与程序设计第7周作业)目标<了解并使用循环结构>作业正文https://i.cnblogs.com/p......
  • 2023-2024-1 20231302 《计算机基础与程序设计》第七周学习总结
    作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第七周作业这个作业的目标数组与链表、基于数组和基于链表实现数据结构、无序表与有序表、树、图、子程序与参数作业正文https://www.cnblogs......
  • CF1304E 1-Trees and Queries(lca+树上前缀和+奇偶性)
    题目二话不说,直接按题意模拟暴搜,当然\(O(nq)\)的复杂度显然是寄了的。不过,在模拟的过程中,我在链式前向星的删边中居然一开始错了,还是要mark一下以后注意。voiddel(intx,intpre){ e[top].to=e[top].next=0; h[x]=pre;//h[x]=0;<---tip}intmain(){ ......
  • js执行的比dom渲染快很多,执行完一定的js才在页面渲染一次dom,UI渲染是宏任务
    假设HTML有一个按钮id为btn,经过以下操作最终会变成什么颜色?document.getElementById('btn').style='background:blue';document.getElementById('btn').style='background:red';Promise.resolve().then(()=>{document.getElementById('......
  • Go语言开发分布式任务调度 轻松搞定高性能Crontab,技能储备+项目开发
    写在前面最近离职交接空档期,在慕课网上学习了下go语言实现分布式crontab任务调度系统。自己也跟随视频实现了一把(跟原版略有不同)。现把成果记录一下。最终代码:https://github.com/funkol2007/distributed_crontab系统介绍实现目标:实现一个分布式crontab系统。用户可以通过......