if(n[i]!
=-1){
count=n[i];
break;
}
now++;
returncount;
}
2.5小结
原先对页面置换算法掌握不太好,通过这一次的实验让我对页面置换算法包括调入一页,换出一页等都有了较深的理解。
因此有些时候多深入学习,做些实验也有助于对理论知识的掌握。
三、设备管理
3.1目的
模拟实现包括设备的添加和删除,设备的分配和回收,体现设备分配中的设备独立性。
掌握外围设备的体系结构和管理方法。
3.2内容
方法:
假定模拟系统中有K、M、T和P设备,采用安全分配方式。
实现过程:
1、设备管理子系统涉及到系统设备表(SDT)、通道控制表(CHCT)、控制器控制表(COCT)和设备控制表(DCT)来体现输入输出系统的四级结构和三级控制。
我们模拟这样的数据结构来完成对外围设备的管理。
(1)添加设备:
增加对应的设备控制表和系统设备表中的表项,如果需要新建对应的控制器控制表。
(2)删除设备:
删除对应的设备控制表和系统设备表中的表项,如果需要删除对应的控制器控制表。
2、独占设备的分配与回收,创建进程申请独立设备名称,建立起连接通路或阻塞到设备、控制器或通道上面,等待其他归还设备的进程后唤醒;
3、申请设备时,可以通过申请某一类设备来实现设备独立性,将逻辑设备名映射为物理设备。
3.3数据结构
PCB类:
主要职责是存储进程的,以及它所需要申请的设备的名称DCT
以下是对进程控制块PCB的定义
publicclassPCB{
publicStringname;
publicDCTdct;
publicPCBnext;
publicPCB(Stringstr){
this.name=newString(str);
this.dct=dct;
this.next=null;
}
}
图3.1PCB类图
SDT类:
用于记录系统之中全部的设备情况,主要属性有设备的类型type,设备的名称name,以及由它指向的DCT。
而其他的如ltype,lname,ldct是与java可视化有关的标签对象,这里不再赘述。
主要的属性则为构造函数。
SDT的类图如下图所示:
图3.2SDT类图
DCT类:
用于记录具体某个设备的情况,属性主要有设备的类型type,设备的名称name,设备的状态status以及等待队列的队首指针phead,occupyName用于记录该设备现在被哪一个进程占用,coct用来记录与之对应的设备控制器COCT。
其函数除了必要的构造函数外还有setBusy()当设备忙时应做的相应操作,setFree()当设备被归还时各个属性的值应该做的相应操作。
DCT的类图如下所示:
图3.3DCT类图
COCT类:
用于模拟设备管理当中的控制器控制表。
连接着CHCT(通道控制表)和DCT(设备控制表)。
主要的属性有name控制器名称,status控制器的状态包括忙与闲,occupyName表示占用的进程名称。
其他的如lx,ly,rx,ry等等则是与java可视化有关的内容。
主要的函数包含构造函数COCT(Stringname,intnum,CHCTch)设置空闲setFree(),设置忙setBusy()等。
COCT类的类图如下所示:
图3.3COCT类图
CHCT类:
对应于设备控制管理当中的通道,跟前面的类相似也有对应的通道名称name,状态status,占用的进程名称occupyName,另外还有与之对应的COCT,队首指针pHead等。
下图即为CHCT(通道控制表)类的类图:
图3.4CHCT类图
3.4算法设计及流程图
(1).添加设备:
①在界面文本框中输入要添加的设备名称name,设备类型type以及希望与之相连接的控制器名coname;②点击添加设备按钮,首先查看是否存在名为coname的控制器,若没有则提示出错返回;③否则申请一个结点SDT类型的结点pS,DCT类型的结点pD,并分别加入到系统当中去,如下图所示即为添加设备的流程图:
图3.5添加设备流程图
(2).删除设备:
①输入要删除的设备名称name;②根据名称在SDT表中查找与name相同的设备,若没有查找到,则提示出错返回;③否则检查设备是否正忙,若忙则提示无法删除设备并直接返回;④否则将查找到的结点从链表中删除。
(3).添加控制器:
添加控制器时与添加设备类似,但是需要输入的不太相同,需要输入添加的控制器名称,与之连接的通道名称,其他实现地方大致相同。
(4).删除控制器:
输入要删除的控制器名称后先对所有的控制器进行查找,若没找到则提示出错并退出,否则检查与控制器连接的设备是否已经删除,假如有与控制器连接的设备则提示仍有设备与之连接并返回。
若所有的检查完毕后则将所得到的结点删除即可。
(5).申请设备:
①输入要申请设备进程pname和设备名称sname;
②先对已有的进程检查,是否有与当前进程名称相同的,若有则提示出错并返回;
③再对系统设备表SDT查找与之对应的设备若未找到提示出错返回。
④检查完毕后根据DCT状态status查看该设备是否在忙,若忙便将其PCB插入等待队列里。
若空闲则将该设备分配给该进程,并调用DCT中的setBusy();
⑤申请到设备后找出与之对应的控制器,若控制器忙便将进程PCB挂在该控制器的等待队列上,否则将该控制器分配给该进程并调用COCT中的setBusy()函数;
⑥申请到控制器后再找到与控制器连接的通道,若通道的状态status为忙则将进程的PCB挂在队列上,否则将通道也分配给进程并调用CHCT当中的setBusy()将通道状态设置成忙。
(6).归还设备:
①输入要归还的设备名称,若未能查找到该设备,则提示出错返回即可;②检查设备状态status是否为空闲若是空闲则直接返回,否则进入③;
③检查设备上的进程是否形成DCT-COCT-CHCT的通路,若没有则提示进程I/O请求尚未完成返回;
④若已经形成通路,则依次将DCT,COCT,CHCT上的等待进程调度进来,若等待队列为空则调用对应的setFree()即可。
3.5小结
在做实验的过程当中遇到了各种各样的困难,包括使用java的可视化与链表组织结构等。
而且因为理论知识没有掌握牢固,系统在把设备分配给请求I/O的进程后才能进一步申请控制器和通道,结果我做的实验中进程申请设备时若进程挂在设备上后又检查控制器,通道。
因此以后我先要把理论的知识掌握牢固,再做实验,这样才能减少错误做到事半功倍。
四、文件管理
4.1目的
利用交互式命令实现树型目录结构和文件管理。
4.2内容
(1)实验内容和步骤:
在文件中保存目录内容,创建文件或子目录可以用命令行命令:
MD、CD、RD、MK(创建文件)、DEL(删除文件)和DIR。
目录项包括文件或目录名称、类型(文件、目录或空目录项)、创建日期以及下一个目录项指针、下一级目录项指针。
(2)具体过程:
1、创建初始文件,建立根目录的“.”和“..”目录项。
2、显示命令提示符“$”。
3、输入命令后根据命令含义完成相应文件操作:
●MD:
在目录文件中创建子目录,同时搜索当前目录最后一个目录项,并保存指针信息;
●CD:
根据当前目录切换到指定目录;
●RD:
搜索所要删除的目录是否为空目录,若是则删除;
●MK:
在当前目录中创建文件名称;
●DEL:
搜索所要删除的文件是否存在,若是则删除;
●DIR:
列出当前目录的所有目录项。
4.3数据结构
FCB:
结构体FCB标识文件所在的盘块,实验中每一个盘块的大小为512B,而该结构体里num则标明是哪一块。
图4.1FCB结构体
Disk:
模拟磁盘,Disk结构体中有磁盘名name,FAT表,位示图bsign,磁盘的大小size,磁盘当中空闲的大小free,总共的盘块数blockNum,指针pfnow用于指向当前磁盘的目录,指针root指向磁盘的根目录,指针next指向下一个磁盘的结点。
图4.2即为UML结构体图表示。
图4.2Disk结构体
File结构体:
File是用来存储文件和目录信息的结构体,包含name文件或目录的名称,type用来区分是文件还是目录,其中type=1时表示为目录,type=2表示是文件,time是文件或目录的创建时间,size主要用于记录文件的大小,first指针指向的是FAT表当中的第一个盘块,child用于指向子目录当中的头结点,当为文件时child等于NULL,由于每个目录中都有特殊的目录“.”和“..”,“.”的child直接指向自身,“..”的child指向其父目录。
Next指针指向当前目录的下一个结点。
图4.3Fie结构体
FileManage类:
文件管理类,包括添加一个磁盘函数add_Disk(name,size),以及与系统中的命令相对应的md(name),mk(name,size)等函数。
如图4.4所示:
图4.4FileManage类图
4.4算法设计及流程图
(1)md命令的实现:
①先对输入的文件名进行检查,包括是否允许访问,名称是否为空是否有非法符号等,若有一条不满足则提示错误并返回;
②检查当前的目录中是否已经存在与之相同的目录名若已经存在,则提示错误并返回;
③否则利用指针p新申请一个File结点,type为1,name为输入目录名,调用get_time()给结点time赋值;
④在当前链中顺序插入新结点p;
⑤调用init_catalog(p->child)给结点子目录初始化。
图4.5md命令流程图
(2)cd命令的实现:
对于cd命令只需从命令行中提取出要打开的目录名,对链表中的所有结点遍历查找type为1的与name相同的结点,若找到则置pdnow->pfnow=p->child若找不到显示系统找不到路径即可。
实现的代码如下所示:
voidFileManage:
:
cd(stringname)
{
File*p=pdnow->pfnow;
if(name=="\\"){
pdnow->pfnow=pdnow->root;
return;
}
while(p!
=NULL){
if(ToLower(p->name)==ToLower(name)&&p->type==1)
break;
else
p=p->next;
}
if(p==NULL){
cout<<"系统找不到指定的路径。
\n";
return;
}
else
pdnow->pfnow=p->child;
}
(3)rd命令的实现:
利用命令行中输入的要删除的目录名name,对pdnow->pfnow中结点顺序访问,查找type为1同时名为name的结点,若没有找到提示系统未找到指定路径并返回,若找到则检查结点child中是否为空,若不为空则提示子目录不为空并返回,若为空则将结点删除即可。
该部分实现的函数如下所示:
voidFileManage:
:
rd(std:
:
stringname){
File*p,*p1;
if(name.empty()){
cout<<"语法命令不正确。
\n";
return;
}
if(name=="."||name==".."){
cout