SPOOLING技术模拟实现_第1页
SPOOLING技术模拟实现_第2页
SPOOLING技术模拟实现_第3页
SPOOLING技术模拟实现_第4页
SPOOLING技术模拟实现_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

摘要SPOOLing技术实际上是一种外围设备同时联机操作技术。它在输入和输出之间增加了“输入井〞和“输出井〞的排队转储环节,以消除用户的“联机〞等待时间。在系统输入模块收到作业输入请求信号后,输入管理模块中的读过程负责将信息从输入装置中读入输入井缓冲区。当缓冲区满时,由写过程将信息从缓冲区写到外存的输入井中,读过程和写过程反复循环,直到一个作业输入完毕。当读过程读到一个硬件结束标志之后,系统再次驱动写过程把最后一批信息写入外存输入井并调用中断处理程序结束该次输入。然后,系统为该作业建立作业控制块,从而使输入井中的作业进入作业等待队列,等待作业调度程序选中后进入内存运行。系统在管理输入井过程中可以“不断〞读入输入的作业,直到输入结束或输入井满而暂停。在SPOOLing系统中,实际上并没有为任何进程分配,而只是在输入井和输出井中,为进程分配一存储区并建立一张I/O请求表。这样,便把独占设备改造为共享设备。宏观上,虽然是多个进程在同时使用一台独立设备,而对每一个进程而言,它们都认为自己是独占了一个设备。当然,该设备只是逻辑上的设备。SPOOLing系统实现了将独占设备变换为假设干台对应的逻辑设备的功能。关键字:输入井;输出井;存输出进程目录TOC\o"1-3"\h\u266161概述 1132022需求分析 3186452.1系统根本需求 3121042.2系统中的制约关系 476573总体设计 5281755255226250784详细设计 9218374.1存输出进程算法 9199219219814.3存输入进程算法 11280054.4处理进程算法 12190624.5取输出进程算法 12287274.6进程的状态转换算法 1341685测试结果 15254835.1初始界面 15227985.2输入作业 151985716184516总结 172779致谢 1815437参考文献 1918566附录 201概述Spooling,即外围设备联机并行操作,它除了是一种速度匹配技术外、也是一种虚拟设备技术。用一种物理设备模拟另一类物理设备,使各作业在执行期间只使用虚拟的设备,而不直接使用物理的独占设备。这种技术可使独占的设备变成可共享的设备,使得设备的利用率和系统效率都能得到提高。为了缓和CPU的高速性与I/O设备低速性之间的矛盾而引入了脱机输入、脱机输出技术,该技术是利用专门的外围控制机,将低速I/O设备上的数据传送到高速磁盘上;或者相反。事实上,当系统中引入了多道程序技术后,完全可以利用其中的一道程序,来模拟脱机输入时的外围控制机功能,把低速I/O设备上的数据传送到高速磁盘上,再用另一道程序来模拟脱机输出时外围控制机的功能,把数据从磁盘传送到低速输出设备上。这样,便可在主机的直接控制下,实现脱机输入、功能。此时的外围操作与CPU对数据的处理同时进行,我们把这种在联机情况下实现的同时外围操作称为Spooling,或称为假脱机操作。由上述得知,Spooling技术是对脱机输入、输出系统的模拟,相应地,Spooling系统必须建立在具有多道程序功能的操作系统上,而且还应有高速随机外存的支持。Spooling系统主要有以下三局部:⑴输入井和输出井。这是在磁盘上开辟的两个大存储空间。输入井时模拟脱机输入时的磁盘设备,用于残存I/O设备输入的数据;输出井时模拟脱机输出时的磁盘,用于暂存用户程序的输出数据。⑵输入缓冲区和输出缓冲区。为了缓和CPU和磁盘之间速度不匹配的矛盾,在内存中要开辟两个缓冲区。输入缓冲区用于暂存有输入设备送来的数据,以后再传送到输出井。输入出缓冲区用于暂存从输出井送来的数据,以后再传送给输出设备。⑶输入进程和输出进程。利用者两个进程模拟脱机I/O时的外围控制机。输入进程将用户要输入的数据从输入机通过输入缓冲区再送到输入井,当CPU需要输入数据时,直接从输入井读入内存;输出进程把用户要求输出的数据先从内存送到输出井,待输出设备空闲时,再将输出井中的数据经过输出缓冲区送到输出设备上。如图1.1所示,为Spooling系统的组成结构图。磁盘输入设备磁盘输入设备输出设备输入缓冲区输出缓冲区输入进程输出进程输出井输入井图1.1Spooling系统组成结构图⑴提高了I/O的速度。这里,对数据所进行的I/O操作,已从对低速I/O设备进行的I/O操作,演变为对输入井或输出井中数据的存取,如同脱机输入输出一样,提高了I/O速度,缓和了CPU与低速I/O设备之间速度不匹配的矛盾。⑵将独占设备改造为共享设备。因为在SPOOLing系统中,实际上并没有为任何进程分配设备,而只是在输入井或输出井中位进程分配一个存储区和建立一张I/O请求表,这样,便把独占设备改造为共享设备。⑶实现了虚拟设备功能。宏观上,虽然是多个进程在同时使用一台独占设备,而对于每一个进程而言,他们都会认为自己是独占了一个设备。当然,该设备只是逻辑上的设备。SPOOLing系统实现了将独占设备变换为假设干台对应的逻辑设备的功能。2需求分析2.1系统根本需求将Spooling输入/输出处理程序编成一个独立的进程模块并且与其它请求输入或请求输出的进程并发运行。Spooling进程负责把从输入设备读入的信息送到外存输入井中,或把外存输出井中的信息送到打印机等输出设备上输出。将整个系统分为三个模块:输入模块、处理模块以及输出模块。〔1〕输入模块〔负责作业的输入〕:首先查看是否有待输入的作业,假设无那么结束。查看输入井是否满,假设满,那么保存待输入作业现场,结束。将作业读入输入井,直到输入井满。设有10道作业待输入,每道作业是一个字符串。长度不超过20,并以“#〞作为结束符号。〔2〕处理模块〔负责加工处理输入井中的作业〕:首先查看是否还有已加工但未送到输出井的信息〔假设有,转向3〕。从输入井中读出一道作业,在作业中的每个字符间插入“.〞。查看输出井是否满,假设满,那么保存现场,结束;否那么将处理过的作业送到输出井中。假设作业全部送入,那么结束;否那么说明作业还未送完而输出井满了,那么保存现场,结束。〔3〕输出模块〔负责将输出井中处理后的作业输出〕:查看输出井是否空,假设空,那么结束;否那么从输出井中依次读出字符送到计算机屏幕显示,遇到“#〞需换行。根据设计要求,我们按照自己的理解,对Spooling系统的设计做出了如下改动:〔1〕Spooling输入进程就是将作业送至输入井。在设计中,为了方便,我们称之为存输入进程。〔2〕Spooling输出进程就是将输出井中的作业送至输出设备打印出来。在设计中,我们称之为存输出进程。〔3〕按照设计要求,处理模块涉及到从输入井中取作业进程处理,处理完毕后将作业送至输出井中。我们认为可以将处理模块分为两局部,一是负责从输入井中取作业进行处理,一是负责将处理的作业送至输出井,这样划分更加清晰。我们将前者仍然称为处理进程,将后者称为存输出进程,根据设计要求以及Spooling系统的原理,可以分析出,处理进程处理完一道作业后,调用存输出进程,将处理后的作业送至输出井。〔4〕为了模拟输入设备以及输入缓冲区,在设计中,当系统运行时,用户可以根据自己的需要将作业通过键盘输入至一二维数组中,然后存输入进程将二维数组中的数据送至输入井。这样,键盘作为输入设备,用二维数组模拟输入缓冲区。2.2系统中的制约关系〔1〕根据Spooling系统的原理,分析得出系统中存在的制约关系如下:图2.1图2.1Spooling系统中的制约关系图满空空阻塞唤醒唤醒满阻塞阻塞输入井处理进程存输入进程取输出进程存输出进程阻塞阻塞输出井唤醒唤醒〔2〕进程消亡的条件:当所有的作业全部输入至输入井时,存输入进程消亡;当所有的作业全部送至输出井时,存输出进程和处理进程消亡;当所有的作业全部输出至屏幕时,取输出进程消亡;如图2.1所示,为Spooling系统中的制约关系图。3总体设计进程有三个根本状态:就绪状态、执行状态、阻塞状态。就绪状态是指当进程已分配到出CPU一位的所有必要资源后,只要获得CPU,便可立即执行,在一个系统中处于就绪队列的进程可能有多个,通常将它们排成一个队列,称为就绪队列;执行状态是指进程已获得CPU,其程序正在执行,在程序中,当调用代表某个进程的函数时,那么表示该该进程处于执行状态;阻塞状态是指正在执行的进程由于发生某事件而暂时无法继续执行时,便放弃处理机而处于暂停状态,亦即进程的执行受到阻塞。根据Spooling系统原理以及我们自己的理解,应该设计四个进程,分别命名为:存输入进程,处理进程,存输出进程,取输出进程。其中,存输入进程是将输入缓冲区中的作业送至输入井中;处理进程是先从输入井中取出作业的数据,然后进行相应的处理;存输出进程是将处理过的作业送至输出井中;取输出进程是将输出井中的数据送至输出设备〔显示器〕上打印出来。输入设备为键盘,当系统开始运行后,给出用户提示,用户通过键盘将自己的作业输入至输入缓冲区〔二维数组〕中,然后开始进程调度。为了方便简单,采用非抢占式调度〔直至进程结束或者阻塞时,才把处理机分配给其他进程〕。为了实现四个进程的调度,设计一个就绪队列和一个阻塞队列,用来存放被阻塞或者就绪的进程的编号;利用两个循环队列来模拟输入井和输出井。首先创立四个进程的PCB,在进程控制块中主要有进程的编号以及进程的状态标识。在开始时,先将四个进程的状态设为就绪状态,并且将存输入进程、处理进程以及取输出进程送至就绪队列,因为处理进程调用存输出进程,不用单独将存输出进程送入就绪队列,当存输出进程被阻塞时,同样会阻塞处理进程。整个运行过程是:从就绪队列中取出一个进程,先进入就绪队列中的进程先被分配CPU。假设进程遇到被阻塞的事件后,那么进入主动阻塞状态,进入阻塞队列。如果该进程在运行的过程中,满足了某个进程所需的数据,那么设置某个进程的状态,并且送入就绪队列中,从阻塞队列中删除。直至所有的作业输出完毕,所有的进程进入结束状态,释放进程PCB。刚开始时是运行存输入进程,在运行过程中如果发现输入井已满时,那么设置自己的状态为阻塞状态,假设所有的作业已经全部输入至输入井中,那么进程结束;当存输入进程阻塞时,那么从就绪队列中取出下一个进程,将处理机分配给该进程,运行。如此循环,当取输出进程将所有的作业全部送至输出井时,那么所有的结束,释放所有的进程PCB。在设计中,当输入井满而作业还没有完全输入至输入井中时,要保存现场。同样,当输出井满,为一道作业还没有完整输入至输出井时,要保存现场,当下次执行该进程时,从断点处继续执行存输入。〔1〕全局变量的定义各个进程间的数据交换是以变量为介质的,变量的定义非常重要,分析在C语言中全局变量时静态存储方式,也就是在编译时开辟内存空间的,全局变量的作用域是整个文件,根据设计原理,一些变量必须要定义为全局变量。SPOOLing系统要模拟输入井、输出井,用循环队列来模拟输入、输出井;就绪队列和阻塞队列都用循环队列来表示;进程控制块用结构体来表示,同时要设置一些整型变量和数组,例如记录带输出作业的数目、记录待输入作业的信息等等。如下所示,为整个系统用到的全局变量。#include"stdio.h"#defineJOBNO3//宏定义作业的个数#defineLENsizeof(structpcb)#defineLEN1sizeof(structReady)structpcb//进程控制块{ intno;//进程编号 intstate;//进程状态,0:可执行状态}*p0,*p1,*p2,*p3;//由于输出井满,存输出进程阻塞,〔2〕主函数主函数中主要实现的是控制作业的输入、进程的创立、就绪队列和阻塞队列的初始化以及进程之间的状态转换和调度。控制作业的输入主要是利用双重循环来控制的,实现进程的调度主要是利用while循环和switch语句配合实现的。当所有的进程都结束后,整个运行过程结束,释放所有的进程。voidmain() { intm,n; printf("********欢送进入SPOOLING模拟系统***********\n"); printf("请输入所有作业内容,字符串,每个字符串以#结束,字符串长度不大于19〔包括#〕\n");//由于字符串最后以‘\0’结束,需要占用一个字符空间 printf("请输入完一道作业后,按回车键\n");}〔3〕存输入进程存输入进程主要完成的是将作业输入至输入井,用到了全局变量js[2]来记录待输入作业的信息,js[0]记录待输入作业编号,js[1]记录待输入作业中要输入的字符位置。voidstore_in()//存输入{ return;}〔4〕处理进程处理进程主要完成的功能是从输入井中取出一道作业进程处理,然后将处理的作业通过调用存输出进程送至输出井中。首先要判断当前是否有已经处理完毕,但是还没有完全送至输出井的作业,如果有,要先将该作业送至输出井。然后再进行下一道作业的处理。主要用到了两个全局变量:记录待输出至输出井中的作业数的整型变量,记录由于输入井空而没有取到完整作业时下次取的数据放的位置。voidchuli(){ return;}〔5〕存输出进程存输出进程主要完成的是把处理完的作业送至输出井中。voidstore_out(int*i)//存输出,由处理进程调用{ return;}〔6〕取输出进程取输出进程主要完成的是把输出井中的数据输出打印出来,主要用到了记录待输出作业数的全局变量,当待输出作业数为0时,说明已经把所有的作业输出打印完毕,进程消亡。在打印输出数据时,遇到‘#’执行换行操作。 voidload_out()//取输出,打印{ return; }〔7〕进程状态转换函数进程状态转换函数主要完成的是唤醒进程,首先根据得到的参数值到就绪队列里查看有没有该进程编号,假设有,那么不进行操作,假设没有,那么该进程入就绪队列,出阻塞队列。该函数是一个带整型参数的函数。voidwait_to_ready(intz)//入就绪队列,从阻塞队列中删除{return;}4详细设计4.1存输出进程算法存输出进程主要完成的是将处理进程处理的作业送入输出井,当输出井满时,该进程阻塞;当取输出进程从输出井中取得数据打印输出时,如果该进程之前由于输出井满,那么取输出进程唤醒该进程。定义两个循环队列指针:q_out.front〔循环队列头指针〕q_out.reat(循环队列尾指针),循环队列输出井的长度为20。首先通过语句(q_out.rear+1)%20!=q_out.frontshi;检测输出井是否满。假设满,那么结束。假设输出井未满,将处理模块已加工后的作业通过语句q_out.date[q_out.rear]=buf[*i];存人到输出井中。在处理后的作业存人到输出井的过程中遇到符号“#〞时,表示一道作业已经完全输入至输出井,为作业创立请求输出表。一道作业处理完毕并且已经全部输至输出井,可以开始下一道作业的处理。在处理后的作业存入到输出井的过程中,假设输出井满,存输出的进程阻塞,保存待输入作业现场,结束。该进程由阻塞状态到就绪状态时,作业从保存现场的待输入作业开始执行。整体控制实现的功能是:提示用户输入作业,创立进程,并将创立的进程全部入就绪队列,通过循环语句来实现所有的进程控制。首先从就绪队列中取出队列的首个数据,利用switch语句来进程匹配,当取出的数据为0时,那么转入执行存输入进程;假设取出的数据为2时,那么转入执行处理进程〔在处理进程中调用存输出进程〕;假设取出的数据为3时,那么转入执行取输出进程。当进程由于某个原因而进入阻塞状态,返回至主函数〔整体控制函数〕,接下来应该判断该进程的状态,假设为阻塞状态那么将该进程的编号送入阻塞队列,从就绪队列中删除,实现该进程的状态转换。假设判断当前进程为结束状态,那么将直接从就绪队列中删除。只有当取输出进程结束时,整个流程才能结束,所以while循环的结束条件就为取输出进程的状态为结束。当循环结束后,要释放进程。为了表达出输入设备以及输入缓冲区,在整体控制中,可以让用户根据自己的需要来输入作业,在输入作业时要根据作业的要求进行输入,输入一个数组,该数组用来模拟输入缓冲区。当输入的作业不符合要求时,要给出提示,让用户重新输入。为了实现程序的扩充,可以利用宏定义来记录整个流程中的作业总数〔而不是设计要求中的仅仅限于10道作业的处理〕。如图4.1所示,为整体控制算法流程图。用户重新输入作业用户重新输入作业初始化输入/输出井创立进程,设置为就绪状态,入就绪队列作业全部输入i++输入合理用户一道输入作业NYNYY开始Y取输出进程为结束状态为阻塞状态就绪队列进程出队,获得进程编号N进程编号存输入进程处理进程取输出进程入阻塞队列N结束图4.1整体控制流程图224.3存输入进程算法存输入进程主要是表达将输入设备中的数据读到输入井中的过程。如果输入设备中有数据需要被读入至输入井,那么首先要判断输入井中是否已经满,如果输入井已经满,那么就无法向输入井中写数据,也就是说不能将作业输入至输入井中,存输入进程就会阻塞,这时需要保存待输入作业现场,程序结束。开始Y开始YNY读至输入井输入井满?待输入作业个数减一作业全部读完?处理进程进入可执行状态N有待输入job?结束保存待输入作业现场进程阻塞NY假设输入设备中的所有待输入作业已经全部输入至输入井,那么该进程结束。如果待输入作业只输入了一局部输入井便已满,那么就不能再向输入井中输入作业,此时应该记录待输入作业的状态,即保存待输入作业的现场。程序中用数值数组JS[2]保存输入作业的信息,其中JS[0]记录待输入作业的编号,JS[1]记录待输入作业中要输入的字符位置。当输入井中的数据被取出后,那么输入井中就又有了空间,那么待输入作业可以继续存入输入井,因为已经保存了待输入作业现场,那么未输完的作业就可以继续被输入至输入井,如此反复,直到所有作业都被输入至输入井,进程结束。如图4.2所示,为存输入进程算法流程图。4.4处理进程算法处理进程完成的功能是从输入井中取得数据,进行处理后,将作业送至输出井等待输出。如果输入井空,那么该进程进入阻塞状态,如果输出井满,同样该进程因为存输出进程被阻塞而进入阻塞状态。根据设计要求得出,要处理完一道作业后再进行输出,用一个buf[]数组来记录处理后的作业,用一个全局整型变量chuli_address来记录当前由于输入井空而阻塞时当前作业待处理的字符位置,也就是保存现场。当从输入井中取得的数据为‘#’,那么表示一道作业已经处理完毕〔在处理过程中,把从输入井取得的数据送至buf[]数组,然后在数组中当前的下个位置中输入‘.’,这样完成处理过程的〕,应该进行存输出,即将处理完的作业送至输出井,也就是说接下来要调用存输出进程。如果调用存输出进程返回后,判断存输出进程阻塞了,那么将处理进程设为阻塞状态〔因为处理的作业不能输出,也就是说I/O请求没有满足,阻塞〕。如果发现存输出进程仍然处于可执行状态,说明存输出进程已经将一道完整的作业送至输出井中,接下来应该判断是否所有的作业已经全部处理完毕并且送至输出井中,如果是,那么处理进程和存输出进程结束;如果不是,那么继续进行下一道作业的处理,此时应该设置chuli_address为0,要将下一道作业的数据依次从buf[]数组的开始位置存储。如果因为存输出进程阻塞而致使处理进程阻塞,当下一次执行处理进程时,首先要判断之前作业有没有完全送入输出井,这就要利用处理进程中的chuli_address变量和存输出进程中记录当前作业待送至输出井字符位置的全局整型变量i进行比拟。如果两个整型变量相等,那么说明之前的作业已经完全输入至输出井,可以开始下一道作业的处理;如果不等,那么说明之前作业虽然处理完毕,但是还没有完全送至输出井中,要先将该作业完全送至输出井才可以开始下一道作业的处理。如果输入井非空,即可以进行作业的处理,当从输入井中取得数据时,如果存输入进程之前由于输入井满而进入阻塞状态,那么唤醒存输入进程。即处理进程从输入井中取得数据后,输入井有空闲空间了,存输入进程所期待的事件发生了,进入就绪状态。输入井和输出井都是利用循环队列模拟的,当输入井为空时,要阻塞该进程,在算法中只需利用语句q_in.front!=q_in.rear来作为循环的条件即可。4.5取输出进程算法取输出进程主要完成的是将输出井中已经处理完毕的作业输出至屏幕打印出来,输出设备即为显示器。首先判断是否所有的作业已经全部输出打印,设一个整型变量来记录待输出打印的作业数,如果该变量值为0,那么说明所有的作业输出打印完毕,进程结束,整个流程也就结束了。如果该变量值大于0,那么说明还有作业没有输出打印,继续从输出井中取得数据。如果当前数据为‘#’,那么说明一道完整的作业已经输出打印完毕,根据设计要求,遇到‘#’换行,继续打印输出下一道作业。取数据时,如果发现输出井空了,那么取输出进程进入阻塞状态。只有当存输出进程将数据送至输出井时,才唤醒该进程,进入就绪队列。当从输出井中取得数据后,应该唤醒存输出进程,因为取出数据后,输出井中有空闲了,可以继续向输出井中送数据,也就是说存输出进程请求的事件已满足,进入就绪队列。每当遇到一个‘#’时,记录待输出打印的整型变量值减1。为了实现每次运行时都能够保持最新的数据,应该将该整型变量设为全局变量。通过循环队列首指针的移动来取出数据,同时当首指针和尾指针相等时,那么表示输出井空,取输出进程的状态要设为阻塞状态,返回至主函数,入阻塞队列。4.6进程的状态转换算法当被阻塞进程所期待的时间发生时,如I/O完成或其所期待的数据已经到达,那么由有关进场能够调用唤醒原语,将等待该时间的进程唤醒。唤醒原语执行的过程是:首先把被阻塞的进程从等待该时间的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就绪,然后再将该PCB插入到就绪队列中。如果在某进程中调用了阻塞原语,那么必须在与之相合作的另一进程中或其他相关的进程中安排唤醒原语,以能唤醒阻塞进程。进程的阻塞是一种自身的主动行为,四个进程会由于某个原因而进入阻塞状态,实现该进程的唤醒操作就是利用进程的状态转换算法来代替唤醒原语。进程的状态转换算法主要实现的是,当一个进程释放另一个进程时,设置就绪队列和阻塞队列应有的变化。该算法被4个进程调用,被其他进程唤醒的进程的编号都是不同的,所以当某个进程要唤醒某个进程时,除了设置被唤醒进程的状态,还要将被唤醒进程的编号作为实参,调用该状态转换算法。在该算法中,首先要判断传送的进程编号在就绪队列中是否存在,假设存在那么说明该进程之前没有被阻塞,注意,在此时如果还将该进程编号送至就绪队列,那么进程的调度可能会出现问题。如果该进程的编号在就绪队列中不存在,那么将该进程入就绪队列,同时要修改阻塞队列,即到阻塞队列中找到该进程的编号,利用循环队列的特点,将该进程编号从阻塞队列中删除。在就绪列中寻找进程编号时,通过移动队列指针来实现的,注意,如果没有找到进程编号时,应该恢复队列之前的指针状态〔事先利用一个变量来记录就绪队列的指针状态〕。5测试结果5.1初始界面运行程序后,就会进入SPOOLing模拟系统。首先看见的是初始界面。初始界面是提示用户已经进入了SPOOLing模拟系统,提示用户要输入所有的作业,每个作业都为字符串形式并以“#〞号结束,包括“#〞号在内的长度不能大于19,如图5.1所示。当用户输入的作业不符合要求时,将给出错误提示,提示用户重新输入作业,如图5.2所示。图5.1初始界面图5.2错误提示信息5.2输入作业在用户进入初始界面后,根据初始界面上的提示,用户需要按照要求输入所有的作业,每输入一道作业按回车键,系统会提示用户继续输入下一道作业,直到作业完全被输入为止,用户输入作业的数目时可以变化的,通过改变宏定义的值,就可以满足用户的要求。如图5.3所示,为输入作业时的过程。图5.3输入作业当用户已经将所有作业都输入以后,系统会提示“您已经把所有作业输入完毕〞,然后系统会执行各个进程,并会在屏幕上输出进程运行的结果,包括存输入进程、处理进程、存输出进程、取输出进程。根据输入作业的长度不同,四个进程调度的顺序不同,比方说,如果输入的作业能够全部输至输入井而输入井不满,在这种情况下,存输入进程进入结束〔消亡〕状态,在之后的进程调度中,不会出现存输入进程的信息。如图5.4、5.5所示,为进程不同的调度顺序下的运行结果。图5.4存输出进程在作业没有全部送至输入井时输入井满而被阻塞时的运行情况图5.5存输入进程在输入井未满的情况下结束的运行情况6总结这次课程设计历时两周,然而我们收获的却远远超过两周的学习所得。通过课程设计,发现自己的很多缺乏,自己的知识有很多漏洞,看到了自己的实践经验还是比拟缺乏,理论联系实际的能力还急需提高。课程设计是培养学生综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对我们的实际工作能力的具体训练和考察过程。随着科学技术开展的日新月异,当今计算机应用在生活中可以说得是无处不在。在这样的开展趋势下,就要求我们必须对自己的专业课程有一个很好的把握和了解。这次操作系统的课程设计就是一个很好的时机。短短的两周时间,不仅让我们了解了SPOOLing系统,更重要的还让我学会了、或者说是验证了“做事一定要有次序和对事物的总体把握〞这句话。由于教材上对SPOOLing系统的介绍并没有用很多笔墨,所以我们在刚开始拿到这个选题时觉得有些无处下手,然而结合教材上的介绍,网络上的资料以及老师给的课程设计任务书,让我们对SPOOLing系统有了比上课时更深一步的了解,不再是以前的只懂一些根本概念而已了。这次的课程设计让我们获益良多,只有懂得了理论与实际相结合的重要性,把所学的理论知识与实践结合起来,从理论中得出结论,才能真正为社会效劳,从而提高自己的实际动手能力和独立思考的能力。致谢在这段课设的日子里,我们对以前在课堂上学到的很多的理论知识有了更深刻的理解。操作系统是门理论与实践结合十分紧密的学科。只有在实践上实现了才能证明你掌握了这个知识点。虽然课设结束了,但是它所带给我们的收获将会在将来的道路上一直陪伴着我们。在这里,要多感谢马生菊老师的帮助,在课程设计的过程当中,如果没有马师的指点,可能我们就不会完成的那么顺利,或者说会在此根底上走很多的弯路。在设计的过程中,我们曾遇到很多问题,但是因为又马老师的帮助,每次我们都能迎刃而解。这两周以来,除了在知识方面有所收获和提高之外,在和其他同学的配合和沟通上也有很大的收获。同学间毫无私心的帮助,真诚的相互鼓励加油,一起分担工作的压力,更一起分享成功带来的喜悦,这次的课程设计更象是一个集体活动,拉近我们彼此的距离,填补了曾经存在的隔膜,集体主义的魅力得到了彻彻底底的展现!我们所接触到的工作,都是需要几个人密切配合才能圆满的完成的,如果大家配合不好,会起到事倍功半的效果。一个工程,是不可能仅凭一人之力完成的,没有相互间的配合,是不可能到达预期的效果的。所以,我们再掌握专业知识的同时,还必须学会相互合作、相互配合。在这次课程设计的过程中,收获知识,提高能力的同时,我们也学到了很多人生的哲理,懂得怎么样去制定方案,怎么样去实现这个方案,并掌握了在执行过程中怎么样去克服心理上的不良情绪。遇到问题时,知道如何寻求解决的方法。因此在以后的生活和学习的过程中,我们一定会把课程设计的精神带到生活中,不畏艰难,勇往直前!参考文献[1]凤羽.操作系统.北京:电子工业出版社,2004[2]马季兰,冯秀芳等.操作系统原理与Linux.北京:人民邮电出版社,2000[3]孟静.操作系统原理教程.北京:清华大学出版社,2000[4]周苏,金海溶.操作系统原理实验.北京:科学出版社,2000[5]孟庆昌.操作系统教程.北京:电子工业出版社,2004[6]陈向群,杨芙清.操作系统教程.2版.北京:北京大学出版社,2006[7]黄干平,陈洛资.计算机操作系统.北京:科技出版社,1989[8]冯耀林,杜舜国.操作系统.西安:西安电子科技大学出版社,1989[9]黄祥喜.计算机操作系统实验教程.广州:中山大学出版社,1994[10]周帆,潘福美.32位微型计算机原理与应用.北京:气象出版社,1992附录源代码:#include"stdio.h"#include<windows.h>#defineJOBNO3//宏定义作业的个数#defineLENsizeof(structpcb)#defineLEN1sizeof(structReady)structpcb//进程控制块{intno;//进程编号 intstate;//进程状态,0:可执行状态}*p0,*p1,*p2,*p3;//由于输出井满,存输出进程阻塞,//2:输入井为空,用户进程阻塞,//3:输入井满,存输入进程阻塞,用户进程阻塞,//4:结束struct{chardate[30]; intfront;//队首指针 intrear;//队尾指针}q_in;//输入井struct{chardate[20]; intfront; intrear;}q_out;//输出井structReady{intdata[4];//存放进程的编号 intfront; intrear;}ready;//就绪队列structWait{intdata[4]; intfront; intrear;}wait;//阻塞队列intchuli_number=0;intjs[2]={0,0};//记录待输入作业的信息,JS[0]记录待输入作业编号,JS[1]记录应该输入的字符位置intjout=JOBNO;//待输出作业数,每输出完一道作业,值减1charbuf[40];//用于存放已经处理完的一道作业intin=JOBNO;//用来记录待输入作业的个数charjob[JOBNO][20];//模拟输入缓冲区intchuli_address=0;//记录作业没有被处理完时,待处理字符的位置inti=0;//用来记录的是下次输入至输出井时从哪里开始写voidstore_in()//存输入{voidwait_to_ready(intz); printf("存输入进程运行\n"); while((q_in.rear+1)%30!=q_in.front)//输入井没有满的情况下 {q_in.rear=(q_in.rear+1)%30; q_in.date[q_in.rear]=job[js[0]][js[1]]; p2->state=0;//处理进程进入可执行状态,//因为输入井不为空了 wait_to_ready(2); if(job[js[0]][js[1]]=='#')//该作业已经输入完毕 {js[0]++;js[1]=0; in--;//待输入作业的个数 if(in==0) { printf("所有的文件已经全部输入至输入井!存输入进程结束\n"); p0->state=4;//存输入的进程结束 return; } } elsejs[1]++; } printf("输入井已满!进入阻塞队列\n"); p0->state=3;//输入井满,存输入进程阻塞 return;}//只有当buf[40]中存的是一道完整的处理过的作业,才输至输出井voidchuli(){voidwait_to_ready(intz); printf("\n处理进程在执行\n"); intp=0; voidstore_out(int*); //存输出函数声明 if(i==chuli_address)//说明该作业已经完全输入至输出井 {chuli_address=0; i=0; } else//i!=chuli_address说明该作业还没有完全输出至输出井 { for(p=0;p<40;p++) if(buf[p]=='#')break; if(p!=40) {chuli_address=p; store_out(&i);//该进程以及处理完毕并且还没有完全至输出井 if(p1->state!=0) {printf("处理进程阻塞\n"); p2->state=3; return;//存输出进程由于输出井满被阻塞相当于用户进程被阻塞 } else {printf("处理完一道作业,开始下一道作业的处理\n"); chuli_address=0;//已经全部输入至输出井,开始下一道作业处理,在buf[]中从头存储〔设置0〕 i=0; } } } while(q_in.rear!=q_in.front)//在输入井未空的情况下 {q_in.front=(q_in.front+1)%30; buf[chuli_address]=q_in.date[q_in.front];//将输入井中数据送入用户进程 if(p0->state!=4) {p0->state=0;wait_to_ready(0);//从输入井中取得数据,有空余地方,设置存输入的进程进入可执行状态 } if(buf[chuli_address]=='#')//每道作业的结束符号是‘#’,在‘#’之后不插入'.' {chuli_number++;//已经处理完毕的作业数 if(p1->state==0) {store_out(&i); if(p1->state!=0)//如果输出井已满,存输出进程被阻塞,那么处理进程被阻塞 {printf("处理进程阻塞\n"); p2->state=3; return; } else {if(chuli_number<JOBNO)//还没有处理完毕所有的作业 {printf("处理完一道作业,开始下一道作业的处理\n"); chuli_address=0; i=0; } else {printf("所有作业已经处理完毕,处理进程结束\n"); p2->state=4; printf("所有作业已经完全送至输出井,存输出进程结束\n"); p1->state=4; return; } }//一道作业已完全输入输出井,可以进行下一道作业的处理 } else {printf("处理进程阻塞\n"); p2->state=3; return; } } else {chuli_address++; buf[chuli_address]='.';//进行处理 chuli_address++; } } printf("处理进程阻塞\n"); p2->state=2;//输入井为空,I/O请求未满足,用户进程阻塞 return;}voidstore_out(int*i)//存输出,由处理进程调用{voidwait_to_ready(intz); printf("存输出进程在运行\n"); intj=q_out.rear+1;//用变量j来记录当前输出井的队尾指针的下一个空间 while((q_out.rear+1)%20!=q_out.front)//输出井还没有满 { q_out.rear=(q_out.rear+1)%20; q_out.date[q_out.rear]=buf[*i]; if(p3->state!=4) {p3->state=0; wait_to_ready(3); } if(buf[*i]=='#') { return;//一道作业处理完毕并且已经全部输至输出井,可以开始下一道作业的处理 } else { (*i)++;} } printf("存输出进程阻塞\n"); p1->state=1;//输出井满,存输出的进程阻塞 return;} voidload_out()//取输出,打印{voidwait_to_ready(intz); printf("\n取输出进程在运行\n"); if(jout<=0) { printf("取输出进程结束\n"); p3->state=4;//取输出进程结束所有进程结束 return; } while(q_out.front!=q_out.rear)//输出井非空 {p1->state=0;//将存输出进程设置为可执行状态,因为有空间存输出了 wait_to_ready(1); q_out.front=(q_out.front+1)%20; if(q_out.date[q_out.front]!='#') {printf("%c",q_out.date[q_out.front]);} else {printf("#"); printf("\n");//一道作业输出完毕,遇到#换行 jout--;//输完一道作业,待输出作业减1 if(jout<=0) {printf("取输出进程结束\n"); p3->state=4;//取输出进程结束所有进程结束 return; } } } printf("取输出进程阻塞\n"); p3->state=2;//由于输出井空,而进入阻塞 return; }voidwait_to_ready(intz)//入就绪队列,从阻塞队列中删除{intp=ready.front; while(ready.front!=ready.rear) {ready.front=(ready.front+1)%4; if(ready.data[ready.front]==z){ready.front=p;return;}//在就绪队列中有该进程 } if(ready.front==ready.rear) {ready.front=p; ready.rear=(ready.rear+1)%4; ready.data[ready.rear]=z;//入就绪队列 inta; for(a=1;a<4;a++) {if(wait.data[a]==z)//从等待队列中删除 {while(wait.rear!=a) {wait.data[a]=wait.data[(a+1)%4]; a=(a+1)%4; } wait.rear--; }//从等待队列中删除 } }}intmain()//主函数 {intm,n; printf("********欢送进入SPOOLING模拟系统***********\n")

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论