目录
一、实验目的
二、实验内容
三、实验思路
四、主要数据结构
五、实现代码
六、实验结果
通过这次实验,理解设备管理的概念和任务。实现设备管理功能的模拟,主要包括通道和控制器的添加和删除,设备的添加、删除,设备的分配和回收。
1、假定模拟系统中已有键盘、鼠标、打印机和显示器四个设备,另有三个控制器和两个通道。
3、实现上述设备、控制器以及通道的层次关系,同时能够添加或删除新的设备、控制器或通道。
4、通过键盘命令模拟进程执行过程中提出的设备分配或释放请求,并为此请求分配或释放设备。分配设备成功后可将进程状态调整为阻塞,释放设备后变为就绪状态。
5、分配设备时应如果该设备已被其它进程占用,则设备分配失败,请求进程进入阻塞状态,同时等待该设备的释放。如果设备空闲,进程占用设备的同时还应提出申请控制器请求,直到与设备相关的通道都已申请成功为止。
通道、控制器、设备的关系:一个通道可以控制多个设备控制器,每个设备控制器可以控制多个设备,属于树型结构关系。
当某进程申请设备时,当且仅当该进程需要的控制器、通道、设备均空闲,才能申请成功,否则需要进入相应的阻塞队列。等待某进程的释放,才能唤醒三个阻塞队列的队首。
本实验为系统初始化若干个设备、控制器、通道,使进程分别申请、释放设备,模拟操作系统的设备管理操作。同时实现设备、控制器、通道的增加和删除。
PCB:记录进程名、申请设备名。
设备、控制器、通道节点:记录名称、占用该节点的进程、等待该节点的进程队列、前驱节点。
链表:设备、控制器、通道表。
等待队列:设备等待队列、控制器等待队列、通道等待队列,由等待节点的进程构成,当进程释放某个节点后,自动唤醒等待队列队首进程。
树型结构:通道、控制器、设备的关系:一个通道可以控制多个设备控制器,每个设备控制器可以控制多个设备。
//pcb
public class pcb {
String name;//进程名
String device;//申请设备名
public pcb(String name, String device) {
super();
this.name = name;
this.device = device;
}
@Override
public String toString() {
return "" + name + "";
}
}
import java.util.Queue;
//通道、控制器、设备的关系:一个通道可以控制多个设备控制器,每个设备控制器可以控制多个设备 树型结构
//通道、控制器、设备节点:
public class Node {
String name; // 名称
pcb process; // 占用该节点的进程
Queue waitinglist; // 等待该节点的进程队列:由进程PCB组成
Node parent; // 父节点
public Node(String name, pcb process, Queue waitinglist, Node parent) {
super();
this.name = name;
this.process = process;
this.waitinglist = waitinglist;
this.parent = parent;
}
}
import java.util.LinkedList;
//设备基本信息节点:
public class sNode {
String name;//设备名称
String type;//设备类型
LinkedList dct;//dct设备控制表
int state;
public sNode(String name, String type,int state, LinkedList dct) {
super();
this.state = state;
this.name = name;
this.type = type;
this.dct = dct;
}
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class IO_management {
public static LinkedList CHCT;//通道控制表
public static LinkedList COCT;//控制器控制表
public static LinkedList DCT;//设备控制表:记录设备使用情况
public static LinkedList SDT;//系统设备表:记录系统中全部设备的情况
public static Queue channel_w,controller_w,device_w; //通道等待队列 控制器等待队列 设备等待队列
public static void main(String[] args) {
// TODO Auto-generated method stub
init();
// showSDT();
while(true) {
Scanner scan=new Scanner(System.in);
System.out.println("**********************************************************************************");
showSDT();
System.out.println("------------------设备管理系统------------------");
System.out.println("1.设备分配 2.设备回收 3.添加设备 4.删除设备");
System.out.println("5.添加控制器 6.删除控制器 7.添加通道 8.删除通道 9.退出");
System.out.println("请输入功能编号:");
int choice=Integer.parseInt(scan.nextLine());
switch (choice) {
case 1:
// showSDT();
System.out.print("请输入进程名:");
String pname=scan.nextLine();
System.out.print("请输入设备类型:");
String dname=scan.nextLine();
allocation(new pcb(pname, dname));
break;
case 2:
System.out.print("请输入进程名:");
String pname2=scan.nextLine();
System.out.print("请输入设备类型:");
String dname2=scan.nextLine();
recovery(new pcb(pname2, dname2));
break;
case 3:
addDevice();
// show();
break;
case 4:
delDevice();
// show();
break;
case 5:
addController();
// show();
break;
case 6:
delController();
// show();
break;
case 7:
addChannel();
// show();
break;
case 8:
delChanner();
// show();
break;
case 9:
System.out.println("-------------------退出程序-------------------");
return;
default:
System.out.println("序号有误!");
break;
}
}
}
//初始化
public static void init() {
//通道控制表
CHCT=new LinkedList<>();
Node c1=new Node("channel1",null,channel_w,null);
Node c2=new Node("channel2",null,channel_w,null);
CHCT.add(c1);
CHCT.add(c2);
//控制器控制表
COCT=new LinkedList<>();
Node co1=new Node("controller1", null, controller_w, c1);
Node co2=new Node("controller2", null, controller_w, c1);
Node co3=new Node("controller3", null, controller_w, c2);
COCT.add(co1);
COCT.add(co2);
COCT.add(co3);
//设备控制表
DCT=new LinkedList<>();
Node d1=new Node("鼠标", null, device_w, co1);
Node d2=new Node("键盘", null, device_w, co1);
Node d3=new Node("打印机", null, device_w, co2);
Node d4=new Node("显示器", null, device_w, co3);
DCT.add(d1);
DCT.add(d2);
DCT.add(d3);
DCT.add(d4);
//系统设备表
SDT=new LinkedList<>();
sNode s1=new sNode("鼠标1", "鼠标",0, DCT);
sNode s2=new sNode("键盘1", "键盘", 0,DCT);
sNode s3=new sNode("打印机1", "打印机",0, DCT);
sNode s4=new sNode("显示器1", "显示器", 0,DCT);
SDT.add(s1);
SDT.add(s2);
SDT.add(s3);
SDT.add(s4);
//等待队列
channel_w=new LinkedList<>();
controller_w=new LinkedList<>();
device_w=new LinkedList<>();
}
//设备分配:DCT->COCT->CHCT
//独占设备:如果该设备已被其它进程占用,则设备分配失败,请求进程进入阻塞状态,同时等待该设备的释放。如果设备空闲,进程占用设备的同时还应提出申请控制器请求,直到与设备相关的通道都已申请成功为止。
public static void allocation(pcb p) {
Node d=null;
sNode f = null;
int num = 0;
//查看设备控制表
for (int i = 0; i < SDT.size(); i++) {
if(p.device.equals(SDT.get(i).type)) {
num++;
if(SDT.get(i).state == 0) {
f = SDT.get(i);
break;
}
}
}
for (int i = 0; i < DCT.size(); i++) {
if (p.device.equals(DCT.get(i).name)) {
num--;
if(num == 0) {
d=DCT.get(i);
break;
}
}
}
if(f == null) {
System.out.println("无设备可用!申请失败");
device_w.offer(p);
return;
}
//该设备已被其他进程占用
if (d.process!=null) {
//进入阻塞队列
System.out.println("设备被占用!申请失败");
device_w.offer(p);
return;
}
else {
//查看其控制器是否空闲
//该控制器被占用
if (d.parent.process!=null) {
//进入阻塞队列
System.out.println("设备控制器被占用!"+p.name+"申请"+p.device+"失败");
controller_w.offer(p);
return;
}
else {
//查看其通道是否空闲
//该通道被占用
if (d.parent.parent.process!=null) {
//进入阻塞队列
System.out.println("通道被占用!"+p.name+"申请"+p.device+"失败");
channel_w.offer(p);
return;
}
else {
//修改各个节点的process信息
f.state = 1;
d.process=p;
d.parent.process=p;
d.parent.parent.process=p;
System.out.println("进程"+p.name+"申请"+p.device+"设备成功");
}
}
}
}
//设备回收:释放进程占用的设备、控制器、通道资源。并唤醒其阻塞队列的一个进程
public static void recovery(pcb p) {
Node d=null;
//查看设备控制表
for (int i = 0; i < DCT.size(); i++) {
if (p.device.equals(DCT.get(i).name)) {
d=DCT.get(i);
break;
}
}
for (int i = 0; i < SDT.size(); i++) {
if(p.device.equals(SDT.get(i).type)&&SDT.get(i).state==1){
SDT.get(i).state = 0;
}
}
System.out.println(p.device+"回收成功!");
//释放设备:修改其process为null
d.parent.parent.process=null;
pcb n1=channel_w.poll();
d.parent.process=null;
pcb n2=controller_w.poll();
d.process=null;
pcb n3=device_w.poll();
//唤醒不为空的阻塞队列的队首进程
if (n1!=null) {
allocation(n1);
}
if (n2!=null) {
allocation(n2);
}
if (n3!=null) {
allocation(n3);
}
}
//添加设备
public static void addDevice() {
Scanner scan=new Scanner(System.in);
System.out.print("请输入设备名称:");
String name=scan.nextLine();
System.out.print("请输入设备类型:");
String type=scan.nextLine();
//将设备添加入SDT
SDT.add(new sNode(name, type,0, DCT));
System.out.print("请输入控制器名称:");
String ne=scan.nextLine();
//查询COCT表
for (int i = 0; i < COCT.size(); i++) {
if (COCT.get(i).name.equals(ne)) {
//将设备添加入DCT
DCT.add(new Node(type, null, device_w, COCT.get(i)));
break;
}
}
System.out.println(name+"添加成功!");
// show();
}
//删除设备
public static void delDevice() {
Scanner scan=new Scanner(System.in);
System.out.print("请输入设备名称:");
String name=scan.nextLine();
//从SDT表中删除
for (int i = 0; i < SDT.size(); i++) {
if (SDT.get(i).type.equals(name)) {
SDT.remove(SDT.get(i));
break;
}
}
//从DCT表中删除
for (int i = 0; i < DCT.size(); i++) {
if (DCT.get(i).name.equals(name)) {
DCT.remove(DCT.get(i));
break;
}
}
System.out.println(name+"删除成功!");
// show();
}
//添加控制器
public static void addController() {
Scanner scan=new Scanner(System.in);
System.out.print("请输入控制器名称:");
String name=scan.nextLine();
System.out.print("请输入通道名称:");
String ne=scan.nextLine();
//将控制器添加入COCT表
//查询CHCT表
for(int i=0;i"+p.parent.name);
}
}
}
public static void show2() {
System.out.println("******************************************");
System.out.println("通道");
for (int i = 0; i < CHCT.size(); i++) {
System.out.println(CHCT.get(i).name);
}
}
}