操作系统课程设计报告内容.docx
《操作系统课程设计报告内容.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计报告内容.docx(58页珍藏版)》请在冰豆网上搜索。
![操作系统课程设计报告内容.docx](https://file1.bdocx.com/fileroot1/2023-1/27/b7f0419f-d22d-4122-87df-41736b450b97/b7f0419f-d22d-4122-87df-41736b450b971.gif)
操作系统课程设计报告内容
1设计目标
编写并调试一个多进程共行的进程调度程序,以加深对进程调度的理解
要求1:
高于实验:
至少有四种以上的进程调度程序供选择;
每个进程由进程控制块表示,进程控制块至少包含6个信息项;
设计一个实用的用户界面,以便选用不同的进程调度算法;
要求2:
独立运行:
有能脱离外部API、支持库及操作系统运行的可能性;
2可行性分析
2.1经济可行性
开始撰写本文档的日期为2011年12月19日,作业提交截止时间为2012年1月3日,因而时间充足,经济上可行。
2.2技术可行性
经过一个对计算机操作系统学期的学习以及之前对汇编、C语言、数据结构等科目学习的知识积累,从技术角度看来,设计中的各项要求均有目前所知的技术能实现的应对方案,技术方面可行。
2.3法律可行性
拟将采用的算法均为公共版权的算法,此外将参考开放源代码的Linux早期版本源代码及Minix早期版本的源代码,可能有部分数据结构或函数引用,因本设计不用于商业用途并将在相应代码上保留原作者信息等荣誉行注释,符合GPL及BSD许可证要求,开发过程所用操作系统及工具均为可免费使用的工具(包括Ubuntu、GCC、NASM、Vim、Bochs、Qemu、VirtualBox、LibreOffice等),法律上可行。
3需求分析
3.1概要分析
根据设计目标的要求1,需要设计的调度程序包含用户界面、相应的数据结构和用户控制函数、内部调度函数,其中内部调度函数中包含至少四种基于不同调度算法的方法,数据结构至少包含一个不少于六个信息项的进程控制块数据结构,用户界面部分包括可供用户选择调度算法的功能模块。
根据设计目标的要求2,程序将不能依靠任何操作系统中的库函数、API实现,因而程序将设计为基于X86兼容机的系统程序,并按照相关协议让程序直接由计算机的BIOS引导加载,使程序能在主流X86虚拟机软件中完整运行。
根据“编写并调试一个多进程共行的进程调度程序,以加深对进程调度的理解”的要求及上述分析,初步确定设计一个严格按照操作系统运行环境运行的调度演示程序,并且每个接受调度的进程拥有自己的进程体及进程体程序,并设计能让进程主动通讯,从加深对操作系统这门课程的角度出发,考虑设计中包含对操作系统一课的大部分内容的应用。
3.2服务流程
3.3服务ER图
4概要设计
基于需求分析(见第三部分需求分析),先设计程序如下:
1、最终生成的程序存放于一个1.44M的磁盘映像文件中,此文件可直接写入到3.5英寸1.44M软磁盘中;
2、上述磁盘镜像可直接用主流X86虚拟机软件(包括VirtualBox、VMWare等)加载运行主程序;
3、基于以上两点,本课程设计将包括磁盘引导区MBR程序及主体程序分别用于引导主体程序及进程调度演示;
4、从上述几点出发,同时为了顺便深入学习一下操作系统的文件系统实现等内容,本设计将包含两部分:
其一为十六位实模式磁盘操作系统用于MBR引导及软磁盘本身存储管理,软磁盘文件系统采用FAT12;其二为保护模式下的多进程系统(一个简易操作系统),即主体程序,将由十六位实模式磁盘操作系统引导加载;
5、面向用户概要设计为:
用户把磁盘塞进计算机(或把磁盘映像放进虚拟机)后,启动计算机,计算机将从软磁盘引导,首先进入到一个磁盘操作系统中,在此磁盘操作系统中通过简单选择或者命令输入将进入进程调度主程序界面,再次界面中可完成进程管理、进程控制以及进程调度管理操作。
6、综上,本设计为一个实模式磁盘操作系统和一个多进程的简易操作系统(如下图):
4.1进程调度演示系统整体模型
整体模型层次图如下图:
4.2实模式软磁盘操作系统模型
模型概要:
如上图所示,对于用户来说,引导进入进程调度系统的引导程序在磁盘中以文件形式静态存在,用户通过操作磁盘操作系统运行引导程序,而对于引导程序来说,实现引导也必须依赖于磁盘操作系统内建的操作系统中断实现读取作为单独文件存放的多进程调度系统内核。
(之所以分开两个文件存放,是因为多进程调度系统设计由C和汇编语言编写并编译为ELF结构文件,读入内存后还必须进行内存分页后按入口地址组织等操作。
)
而对于用户来说,磁盘操作系统的内容只包括显示输出的内容和键盘操作的部分,文件系统的实现、显存操作、中断处理等部分均对其透明。
对于此系统而言,程序由实模式操作系统的引导程序从磁盘映像中读取到内存中执行,而读取到内存的操作需要定位到程序主体在磁盘中的存放位置,这就需要对文件系统进行初步的操作,因此,此系统首先是基于文件系统的。
综上,此程序主体为:
文件系统、中断系统、用户终端(显示输出及键盘操作);
4.2.1文件系统模型
本设计中文件系统包含最终编译生成的1.44M磁盘映像中的数据内容以及实模式磁盘操作系统中对磁盘进行读写操作的部分。
数据组织上,采用FAT12标准进行组织架构,即使磁盘映像中包含正确的主引导记录扇区、两个FAT表、一个根目录区等,因此,此磁盘映像生成时,具备的线性结构如下:
如上图,映像中第一个扇区(头部512字节)中包含跳转到引导程序的指令、FAT12分区的基本信息及引导程序;第一个扇区以后,是9个扇区的FAT1和9个扇区的FAT2,此时,这两个表均表示为分区空间全部闲置;同时根目录区为空。
对于文件系统的操作部分,设计以下几个依赖BIOS的13H号中断的方法:
初始化软驱;
关闭软驱;
把LBA转换成CHS;
根据CHS读取扇区;
根据CHS写入扇区;
获取文件当前簇的下一簇簇号;
设置文件当前簇的下一簇簇号;
根据文件名在当前目录下搜寻文件;
根据文件名删除文件;
读取根/子目录表;
写入根/子目录表;
读入FAT表;
写入FAT表;
读取指定簇;
读取整个文件到内存;
创建文件;
写入文件;
为文件分配一系列簇;
遍历当前目录的文件;
打印遍历的文件信息;
规格化文件条目为文件信息字符串到文件名缓冲区;
文件名缓冲区操作(含大小写规格化、清理等);
规格化目录路径;
读取规格化后的目录路径指向的目录;
考虑到此文件系统只为一张软盘即只有体积极小的FAT表,而可用内存有1MB大小,且内存读写速度远远大于磁盘操作速度,因而设定为运行后直接装载FAT表到内存中读写,因为读取操作远远多于写入操作,因此设定为每次写入时整个FAT表写入。
4.2.2中断系统模型
中断向量表采用8086模式下BIOS默认预设的0:
0内存编址开始的十六位中断向量表。
其中,为了实现部分时钟相关的功能,需要设定中断向量表的8号中断、操作定时器模式、初值等;键盘中断的实现包括设置中断向量表的9号中断;
另外需要自行编写部分引导程序需要调用的操作系统中断,包括编写相应的中断服务程序(如字符串输出、文件读写等,此部分务求与MS-DOS兼容)、设置中断向量表的21H号中断及设置二级中断向量表等。
4.2.3用户终端模型
考虑到拓展性(包括是模式操作系统日后的深入研究拓展等)及用户习惯,实模式操作系统设计为:
最大限度模仿MS-DOS的人机界面。
模仿MS-DOS的人机界面设计
实模式操作系统用户界面如上图,设计为用户键入指令回车后执行指令,并设计实现DIR指令用于显示文件列表、CD指令用于更改当前目录、键入可执行程序名时执行程序等功能;
对于引导进入保护模式多进程调度系统的实现,设计为编写一个名为“boot”的可执行程序放进磁盘中,用户在实模式磁盘操作系统启动完毕后在命令(如上图)中键入“boot”即可完成引导,此部分利用了实模式操作系统执行程序的功能。
考虑到与MS-DOS的兼容性,boot程序将参照COM文件结构编写,同时对是模式操作系统加载程序的实现作出相应的设计。
4.3保护模式下多进程系统模型
模型概要:
在本系统中,用户可见的内容只有进程管理器以及进程在运行时涉及到用户界面显示的操作,用户能操作的只有进程管理器,用户通过操作进程管理器实现进程控制、进程管理、调度控制等功能。
进程调度及涉及硬件的操作均由系统内核完成,作为进程存在的作业或任务只能通过包括消息传递、文本收发在内的系统调用完成涉及硬件的操作。
4.3.1保护模式跳转程序概要设计
由于进程调度系统对系统安全性有较高要求,同时需要的内存在实模式下无法获取,因此本系统需要设计在80386及其后继机型的保护模式下,因而需要一个模式切换的跳转程序。
对于多进程的系统来说,进程的内存寻址、地址编址方式不确定,为了避免冲突,需要采用虚拟内存的方式,因而跳转程序中需要开启X86的分页机制,实现段页式存储管理,因为本系统暂不需要文件系统,因而分页文件可忽略,分页直接映射所有的物理内存;
进程调度的实现、硬件操作均由系统内核完成,进程体不可直接操作硬件,同时为了避免一个进程的错误导致整个系统的崩溃,本系统中需要实现权限分级,因此引导程序中还需要利用X86的Ring0和Ring1两个特权级,并设置相应的GDT以划分各个内存段的权限等级,其中系统内核运行在Ring0,其余运行在Ring1态;
操作系统中需要获得物理内存大小从而实现内存分配等管理,而获取内存大小的兼容性最高的方法是利用BIOS中断,因为实模式下BIOS中断不可用,因而设定在跳转程序中跳转到保护模式前获取内存大小。
当然,跳转程序最重要的工作是从文件系统中查找到系统内核程序的实体文件,加载到内存中,然后按照ELF结构把内核各程序段放置到准确位置上,最后跳转到内核程序入口处,涉及文件系统的操作需要依赖前面实模式操作系统的系统中断,因而读取操作在实模式下完成,而放置内核需要在开启内存分页后,因此在保护模式下完成。
综上,此跳转程序流程如下图:
4.3.2保护模式系统初始化流程
跳转到系统主程序之后,需要进行一系列的初始化操作,包括:
1、设置全局描述符表(GDT)及TSS;
2、编程初始化Intel8259A
3、设置IRQ映射图;
4、设置中断描述符表(IDT);
5、初始化进程将要使用的局部描述符表(LDT)分配表及对栈;
6、强制使用设置的GDT;
7、初始化进程表;
8、初始化文本消息队列;
9、初始化用户表;
10、设置所需的全局变量;
11、插入预设进程;
12、开始进程调度;
4.3.3进程管理器用户界面实现
对于进程管理器的实现,有两种方案:
1、把进程管理器本体作为一个进程实现显示;
2、让进程管理器成为内核的一部分,实时显示当前调度情况;
由于本设计中需要实时切换调度方式,而诸如FCFS一类的方式可能会造成进程管理器本体进程饥饿而无法实现显示进程信息的效果,因此本设计中采用了第二种方案,由此抛弃了把本设计做成一个完成的操作系统的思路,仅实现演示功能。
基于上述设计方案,设计一个刷新显示任务信息的子程序,让此子程序每五个时间片运行一次(每个时间片为10ms),忽略显示处理的时间,大约为20帧/秒的刷新速度。
由于没找全脱离BIOS支持的VGA编程的相关资料,因而用户界面全程采用显卡兼容的Teletype模式,实现80*25的字符界面,限于分辨率大小,只能同时显示不多于25个进程的信息,再加上界面设计,设定用户界面如下:
如上图,进程列表中同时显示最多19个进程包括进程名、用户UID、进程PID、优先计数、优先数、消息队列消息数量、进程状态、睡眠时间、运行时间、需要运行的时间在内的进程信息,并提供调度时间片吧、调度算法、内存信息在内德系统信息。
同样受限于分辨率大小,用户指令设计为命令行形式以容纳更多的指令,进程输出局限在右下角的小窗口里。
键盘操作功能方面,设置环状队列的键盘缓冲区及一个字符数组作为命令缓冲区,设置一个指针指向当前激活的进程,当有进程激活时,对键盘的操作将作为消息发送给进程,当没有进程被激活时,键盘消息由进程管理器处理,进程管理器以回车键为命令结束的标志,键盘方向键或者PageUP、PageDown控制进程列表显示。
对键盘的硬件处理由中断完成,内核每次读入键盘扫描码后识别按键类型,属于ASCII字符则加入键盘缓冲区及命令缓冲区,属于功能键则按功能划分处理。
默认情况下,系统接管键盘,用户输入的指令反馈显示到屏幕上,同时对用户每次回车键操作作一次命令解析,由于命令较少,命令解析可按照无序的字符串比较完成。
4.3.4进程调度所需要的数据结构
本程序通过操作以下数据结构实现进程调度:
1、段描述符的数据结构{
段基址;
段界限;
段属性
};
此数据结构用于全局描述符、局部描述符等,划分特权级及进程(程序)段用;
2、门描述符{
偏移地址;
段选择字;
参数计数;
属性;
};
此数据结构用于调用门、中断门、陷阱门、任务门,实现系统调用、中断等;
3、栈框的数据结构{
各寄存器;
};
此数据结构主要用于进程切换,各寄存器按照切换中压栈顺序排列;
4、TSS的数据结构{
32位TSS的数据结构;
};
此数据结构主要用于特权级切换;
5、文本消息的数据结构{
发送方PID;
接收方PID;
允许阅读次数;
文本消息内容;
};
此数据结构用于传送文本消息,实现方式为建立一个文本消息数组用作信箱,发送文本消息时先把文本消息类型及信箱编号作为普通消息的参数发送至目标进程,目标进程再通过信箱号获取信息,普通消息的数据结构如下:
6、普通消息的数据结构{
发送方PID;
类型;
值;
};
此数据结构用于每个进程各自的消息队列,每个进程拥有独立的若干个普通消息数据结构组成消息队列,当消息队列满后,拒绝接收所有消息,进程可通过系统调用发送消息或轮询接收消息;
7、用户的数据结构{
用户UID;
用户名;
用户的进程数;
};
用于某些进程调度算法;
8、进程控制块的数据结构{
栈框;
局部描述符段选择子;
局部描述符表;
优先数计数(动态优先数);
优先数(静态优先数);
睡眠时间(仍需睡眠的时间);
已运行时间片;
需要运行的时间片;
状态;
用户UID;
消息队列;
消息计数;
进程PID;
进程名;
};
9、任务数据结构{
任务进程体子程序;
栈大小;
任务名;
需要运行的时间片;
优先数;
};
进程的建立基于任务——一个任务体可生成多个同时运行的进程实体;
4.3.5内存空间分配
本程序的运行基于实体计算机或者虚拟机,需要至少32MB的内存,分配情况如下:
设置分页时,设置的页表数和页目录数对应实际内存大小,因32位地址总线最大寻址4GB,即页表最大占4MB,因而预留4MB内存给页表,本程序允许最多256个进程同时运行,栈空间按照平均每个进程32KB进行预算,进程表等数据实体均存放于系统内核中。
4.3.6基于定时器中断的调度模型
本系统中,进程调度的依据是时间片,最小时间间隔单位是10ms,调度间隔可由用户控制,实现流程如下:
如上图,进程切换利用X86保护模式的特权级切换、TSS数据结构,通过定时器中断实现,其中,定时器中断发生时,判断是否需要调度的依据是用户设置的调度时间片,由于当代计算机的性能较高,10ms的调度间隔足够运行任何调度算法,而定时器8253能设置的最小时间间隔也接近10ms,因此设置10ms为默认调度间隔时间片。
4.3.7调度算法选择的实现
对于实时选择调度算法的功能,设计如下:
首先设置一个变量用于记录当前的算法,此变量初值为某个算法(默认调度算法),用户可随时通过指令修改当前算法,修改的值保存在这个变量中。
发生进程调度时,调度器根据用户选择的算法决定运行哪一个调度子程序。
4.3.8调度算法
要求实现至少四种的调度算法,四种基本算法即为课本上介绍的算法:
时间片轮转法、FCFS、静态优先数调度、动态优先数调度,此外,因为用户界面上,显示进程体输出的功能模块参考其他操作系统的设计,由一个用户为0的进程完成,因此引入第五种算法:
参考CFS的用户平分时间片、用户内动态优先调度的算法。
本系统的进程控制块有“要求服务时间”一项信息,因为有不按时间作为完成依据的进程存在,因而设定要求服务时间为0的进程为无限时运行的进程,这样一来,在FCFS及静态优先数算法中必定会造成无法调度,因此,FCFS和静态优先数算法里,系统将不把无限时运行的进程纳入调度范围内。
则五种调度算法总结如下:
默认的调度算法:
每次调度选择不同的用户,再从同一个用户的进程中选择动态优先数最大的进程进行调度,每次调度后动态优先数减1,直到全部可调度进程的动态优先数均为0时,将全部可调度进程的动态优先数重置为初值。
时间片轮转法:
按照进程表的顺序以时间片为单位时间轮转调度。
FCFS:
每次调度PID最小的可调度进程,直到完毕。
动态优先数:
在进程表中选择动态优先数最大的进程进行调度,每次调度后动态优先数减1,直到全部可调度进程的动态优先数均为0时,将全部可调度进程的动态优先数重置为初值。
静态优先数:
每次选择优先数最大的进程进行调度。
4.3.9进程管理、控制功能
进程的管理、控制包括建立进程、结束进程、强迫进程睡眠、修改进程的运行时间、优先数、切换用户、发送消息给进程等。
程序运行后,预设有几个进程,用户可在进程总数不超过最大值的情况下新建进程,每个进程均依照任务体建立,每个任务体均有其对应的子程序,其中,任务体可以复用,作为进程体的子程序也可以复用,进程体的复用依据是:
1、虚拟内存地址;2、局部变量均保存在栈中;3、每个进程拥有属于自己的栈空间。
新建程序时,进程体均为一个默认的子程序——因为本系统没有实现文件系统,所以不可以运行第三方程序作为新进程,进程状态更改为READY,允许调度。
对于时间片用完的进程,标记其为FINISH但不终止子程序,终止子程序的操作只能由用户输入命令完成,终止的进程被标记为DIE。
进程可主动使用系统调用进入睡眠状态,也可以由用户指定睡眠时间进入睡眠状态。
睡眠中的子进程不会被调度器调度,直到睡眠时间结束状态转换为READY为止。
为了防止因为所有进程均进入睡眠状态而导致调度器死锁或调度程序陷入死循环,规定当遍历三次(三次是因为动态优先数算法时,所有进程动态优先数均为0时需要重置优先数,将进行两次遍历)进程列表未找到READY状态或BLOCK状态的进程时,强制将当前进程指定为0号进程,这参照了Linux关于0号进程Init的设定。
4.3.10进程通信、系统调用
在本程序中,系统调用作为软中断存在,中断号为0x80,中断功能号作为系统调用表调用的依据。
系统调用主要包括有根据进程名获取查找进程PID、获取本进程的PID、根据进程PID发送普通消息、根据进程PID发送文本消息、获取本进程消息队列中的消息、根据信箱编号获取文本信息、进程睡眠等。
进程间通信依靠两种消息完成:
普通消息和文本消息。
普通消息的发送需要三个参数:
目的进程PID、消息类型、消息的值。
文本消息的发送需要三个参数:
目的进程PID、文本起始地址、文本允许阅读次数。
由于文本传递中涉及到不同代码段的操作,直接建立文本通道可能会造成错误,因此本设计中采用了文本信箱的方式——进程发送文本后,内核把文本复制到信箱中并返回信箱编号,发送进程再把信箱编号作为普通消息中文本类型普通消息的值传递给目标程序,目标程序轮询自己的消息队列捕获消息类型为文本类型时,取出信箱号并通过获取文本消息的系统调用向系统要求获得消息内容,系统通过对信箱中该信箱号位置的消息数据结构中目标进程PID项与发送请求的进程的PID进行比对后决定是否把文本信息复制到请求进程提供的缓冲区中。
进程发送消息
每条文本信息有允许阅读次数的计数器,每次成功的阅读请求会使该计数器值减1,当其值为0时,该文本消息作废,系统认为其为空信箱,空信箱不允许读取,可写。
同理,当信箱计数值不为0时,系统认为该信箱有消息,不把新消息写入该信箱,当所有信箱均不为空时,系统不允许发送文本消息——当然,这样一来,有可能因为某些进程的恶意发送而导致信箱长期为满载,从而使系统不能正常服务,因此,需要设置一个解决信箱满载的方案,此方案设计为:
目标进程轮询获得文本类型普通消息后,不读取文本消息而继续轮询达到一定次数后抛弃该文本信息;若目标进程经过一定次数的调度后均不轮询消息则认为该进程没有消息处理机制,抛弃以该进程为目标进程的所有文本消息。
内核处理消息
除了文本消息外,普通消息也有可能因为消息队列满载而无法正常接收——这种情况下,需要在进程调度算法中对发送方和接收方得优先数进行调整处理或者交给进程自己处理。
5详细设计
5.1环境、代码及规范
本次设计主要在Ubuntu下用GVIM完成,由于和Windows之间存在UTF-8和Unicode编码的兼容性问题,全部注释用英文字母标注。
源代码的文件格式包括:
1)以.c为后缀的C语言代码文件;
2)以.h为后缀的C语言头文件;
3)以.s为后缀的汇编语言代码文件;
4)以.inc为后缀的汇编语言头文件;
5)无后缀名为bochsrc的Bochs虚拟机配置文件(可选);
6)无后缀名为Makefile的生成文件,命令依赖于Bash;
7)以.img为后缀的磁盘映像文件,也是最终编译生成文件;
8)可能存在后缀带“~”或“swp”的vim交换文件;
9)可能存在的一些工具(程序)文件。
上述文件中,C语言代码遵从C89标准,汇编语言代码采用NASM支持的Intel语法格式,编译器为NASM和GCC,调试环境为Bochs虚拟机及Qemu虚拟机,Makefile中使用了Bash的cp指令、rm指令及mount、unmount指令。
使用Makefile的编译过程如下:
5.2实模式磁盘操作系统的详细设计
实模式操作系统不是本设计的重点,而仅仅作为引导程序的一部分及作为顺带学习一下文件系统的实现用试验品。
由于此系统设计底层操作居多,对算法复杂度要求低,因此完全采用汇编语言编写。
5.2.1功能模块划分
1、实模式磁盘操作系统按功能划分为:
2、操作系统中断模块(对应源代码dos/kernel/dos.s);
3、文件系统功能模块(对应源代码dos/kernel/fs.s);
4、常用内部函数(对应源代码dos/kernel/general.s);
5、全局变量、缓冲区等(对应源代码dos/kernel/global.s);
6、初始化程序体(对应源代码dos/kernel/init.s);
7、中断实现(对应源代码dos/kernel/ints.s);
8、键盘处理(对应源代码dos/kernel/keybord.s);
9、定时器处理(对应源代码dos/kernel/time.s);
10、视频输出模块(对应源代码dos/kernel/video.s);
5.2.2中断实现
中断实现依赖于BIOS默认建立的中断向量表,其中,按照主I8259A的IRQ线,设置8、9号中断向量表的中断向量指向定时器、键盘中断处理服务程序,设置0x21号中断指向内建的DOS中断服务程序(部分兼容MS-DOS)。
dos/kernel/ints.s文件中的主要子程序说明:
_SET_UP_INTS
初始化中断向量表
_SET_INT_HANDLER
设置中断向量
_INT_TIMER
定时器中断服务程序
_INT_KEYBO