实验一:资源分配仿真
实目的
在课程已经学习了死锁的4个必要条件的基础上,为了了解系统的资源分配情况,假定系统中任一资源在每一时刻只能由一个进程使用,任何进程不能抢占其它进程正在占有的资源,当进程得不到资源时,必须等待。因此,只要资源分配策略能保证不出现循环等待,系统就不会发生死锁。 要求学生编写和调试系统动态分配资源的仿真程序,观察死锁产生的条件,再采用适当的算法,有效地防止和避免死锁发生。 PS:实体类使用lombox自动生成getter setter 有参 无参方法(没有的手动生成) lombox maven仓库地址
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
实现方式
随机分配算法产生死锁,银行家算法避免死锁
具体代码
随机分配算法:此算法不是模拟死锁而是会真正产生死锁(多运行几次随机的有的时候不会产生死锁)
package com.xu.demo.ytu.bank;
import java.util.ArrayList;
import java.util.List;
public class RandomAgl {
public static Object A=new Object();
public static Object B=new Object();
public static Object C=new Object();
public static Object D=new Object();
public static void RanDomTest(List<Object> list){
System.out.println(list);
new Thread(()->{
synchronized (A){
System.out.println(Thread.currentThread().getName()+"我得到了资源:"+A);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object O=list.get((int) (Math.random() * 4));
System.out.println("随机分配资源开始:线程"+Thread.currentThread().getName()+"随机去获取的资源是"+O);
synchronized (O){
System.out.println("线程"+Thread.currentThread().getName()+"得到了资源"+O);
}
}
}).start();
new Thread(()->{
Object O=list.get((int) (Math.random() * 4));
synchronized (B){
System.out.println(Thread.currentThread().getName()+"我得到了资源:"+B);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("随机分配资源开始:线程"+Thread.currentThread().getName()+"随机去获取的资源是"+O);
synchronized (O){
System.out.println("线程"+Thread.currentThread().getName()+"得到了资源"+O);
}
}
}).start();
}
public static void main(String[] args) {
List<Object> testList=new ArrayList<>();
testList.add(A);
testList.add(B);
testList.add(C);
testList.add(D);
RandomAgl.RanDomTest(testList);
}
}
运行截图 死锁已经产生,接下来进入java的bin目录具体查看 可以看出,线程1得到了资源270ca0并且想要去获取资源270c90,线程0得到了资源270c90并且想要获取资源270ca0死锁产生
银行家算法: PCB类
package com.xu.demo.ytu.bank;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PCB {
String processName;
int maxUsed;
int alreadyUsed;
boolean isFinish;
@Override
public String toString() {
return
"\t"+processName +
" \t" + maxUsed +
" \t" + alreadyUsed +
" \t" +(maxUsed-alreadyUsed)+
" \t" + isFinish ;
}
}
BankAlg
package com.xu.demo.ytu.bank;
import java.util.*;
public class BankAlg {
public static int availableSource = 10;
public static ArrayList<String> safeList = new ArrayList<>();
public static Map<String, PCB> pcbMap = new LinkedHashMap<>();
public static void init() {
PCB a = new PCB("A", 5, 1, false);
PCB b = new PCB("B", 3, 1, false);
PCB c = new PCB("C", 4, 2, false);
PCB d = new PCB("D", 6, 3, false);
pcbMap.put(a.processName, a);
pcbMap.put(b.processName, b);
pcbMap.put(c.processName, c);
pcbMap.put(d.processName, d);
System.out.println("---------------------------------------初始化--------------------------------------------------");
System.out.println("进程名 " + "最大需求量 " + "占有量 " + " 仍需 " + " 完成");
pcbMap.forEach((k, v) -> {
System.out.println(v);
});
pcbMap.forEach((k, v) -> {
availableSource -= v.alreadyUsed;
});
System.out.println("剩余资源量:" + availableSource);
}
public static void safe(String pName, int pNum) {
if (availableSource < pNum) {
System.out.println("请求不安全 拒绝分配");
} else {
availableSource = availableSource - pNum;
pcbMap.get(pName).alreadyUsed += pNum;
if (pcbMap.get(pName).maxUsed - pcbMap.get(pName).alreadyUsed == 0) {
availableSource += pcbMap.get(pName).maxUsed;
pcbMap.get(pName).isFinish = true;
pcbMap.get(pName).maxUsed = pcbMap.get(pName).alreadyUsed = 0;
}
pcbMap.forEach((k, v) -> {
if (v.maxUsed - v.alreadyUsed <= availableSource && !v.isFinish) {
safeList.add(k);
}
});
if (safeList.size() == 0) {
List<Boolean> checkList = new ArrayList<>();
pcbMap.forEach((k, v) -> {
checkList.add(v.isFinish);
});
System.out.println("请求不安全 拒绝分配");
availableSource = availableSource + pNum;
pcbMap.get(pName).alreadyUsed -= pNum;
if (!checkList.contains(false)) {
availableSource = availableSource - pNum;
pcbMap.get(pName).alreadyUsed += pNum;
}
}
int temp = 0;
for (String s : safeList) {
temp = pcbMap.get(s).maxUsed;
}
int finalTemp = temp;
pcbMap.forEach((k, v) -> {
if (v.maxUsed - v.alreadyUsed < availableSource + finalTemp) {
if (!safeList.contains(k)) {
safeList.add(k);
}
}
});
if (safeList.size() == 4) {
System.out.println("进程名 " + "最大需求量 " + "占有量 " + " 仍需 " + " 完成");
pcbMap.forEach((k, v) -> {
System.out.println(v);
});
System.out.println("安全序列:" + safeList);
System.out.println("剩余资源量:" + availableSource);
}
}
safeList.clear();
}
public static void main(String[] args) {
BankAlg.init();
do {
Scanner in = new Scanner(System.in);
System.out.println("资源申请 请输入进程名:");
String pName = in.next();
System.out.println("请输入申请的资源量:");
int pSum = in.nextInt();
BankAlg.safe(pName, pSum);
} while (availableSource < 10);
System.out.println("分配结束");
}
}
银行家算法运行截图:
文字描述
实验二:可变分区主存空间的分配与回收仿真
实验目的
主存中央处理机能直接存取指令和数据的存储器。能否合理而有效地使用它,在很大程度上将影响整个计算机系统的性能。本实验主要让大家熟悉主存的分配与回收。所谓分配,就是解决多道作业如何共享主存空间的问题;当作业运行完成时,如何回收作业所占的主存空间。主存的分配与回收的实现是与主存储器的管理方式相关的。通过本实验,帮助学生理解在不同的存储管理方式下如何实现主存空间的分配与回收。
使用最佳适应算法实现
具体代码
Free类
package com.xu.demo.ytu.bf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Free {
private int no;
private String processName;
private int begin;
private int end;
private Boolean isUsed;
@Override
public String toString() {
return
"\t" + no +"\t"+
" \t" + processName +"\t"+
" \t" + begin +"\t"+
" \t" + end +"\t"+
" \t" + (end-begin+1) +
" \t" + isUsed ;
}
}
Used类
package com.xu.demo.ytu.bf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Used {
private int no;
private String processName;
private int begin;
private int end;
private Boolean isUsed;
@Override
public String toString() {
return
"\t" + no +"\t"+
" \t" + processName +
" \t" + begin +"\t"+
" \t" + end +"\t"+
" \t" + (end-begin+1) +
" \t" + isUsed ;
}
}
BestFit
package com.xu.demo.ytu.bf;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
public class BestFit {
private static final int cacheBegin=0;
private static final int cacheEnd=400;
private static List<Used> usedList=new ArrayList<>();
private static List<Free> frees=new ArrayList<>();
private static List<Integer> addrNum=new ArrayList<>();
public static void init(){
System.out.println("初始化");
usedList.add(new Used(0,"OS",0,90,false));
usedList.add(new Used(0,"A",91,151,false));
usedList.add(new Used(0,"B",156,166,false));
usedList.add(new Used(0,"C",170,200,false));
usedList.add(new Used(0,"D",260,320,false));
BestFit.used();
BestFit.free();
}
public static void addProcess(String pName,int pSize){
Used pUsed = new Used();
pUsed.setProcessName(pName);
if(frees.size()==0){
System.out.println("内存已满,无法执行此操作");
return;
}
if(pSize==0){
System.out.println("输入有错误!!!");
return;
}
for (Used used : usedList) {
if (used.getProcessName().equals(pName)) {
System.out.println("此进程已经存在,操作失败!!!");
return;
}
}
frees.sort(new Comparator<Free>() {
@Override
public int compare(Free p1, Free p2) {
return (p1.getEnd()-p1.getBegin())-(p2.getEnd()-p2.getBegin());
}
});
if (pSize>frees.get(frees.size()-1).getEnd()-frees.get(frees.size()-1).getBegin()+1){
System.out.println("内存空间不足 进程无法添加!!!");
return;
}
for (Free free : frees) {
if (free.getEnd()-free.getBegin()+1>=pSize){
pUsed.setBegin(free.getBegin());
pUsed.setEnd(free.getBegin()+pSize-1);
pUsed.setIsUsed(false);
usedList.add(pUsed);
return;
}
}
for (Free free : frees) {
System.out.println(free);
}
}
public static void recycleProcess(String pName){
for (Used used : usedList) {
if(used.getProcessName().equals(pName)){
usedList.remove(used);
return;
}
}
System.out.println("此进程不存在,无法回收!!!");
return;
}
public static void used(){
usedList.sort(new Comparator<Used>() {
@Override
public int compare(Used p1, Used p2) {
return p1.getBegin()-p2.getBegin();
}
});
if(usedList.size()==0){
addrNum.add(cacheBegin);
addrNum.add(cacheBegin-1);
addrNum.add(cacheEnd+1);
addrNum.add(cacheEnd+1);
return;
}
if(usedList.get(0).getBegin()!=0){
addrNum.add(cacheBegin);
addrNum.add(cacheBegin);
System.out.println(usedList.get(0).getBegin()-1);
}
int no=1;
for (Used used : usedList) {
used.setNo(no);
addrNum.add(used.getBegin());
addrNum.add(used.getEnd());
no++;
}
if(usedList.get(usedList.size()-1).getEnd()!=400){
addrNum.add(cacheEnd+1);
addrNum.add(cacheEnd+1);
}
System.out.println("-----------------------------------已使用分区表-------------------------------------");
System.out.println(" No \t"+"进行名 \t"+"起始地址 \t"+"结束地址 \t"+" 长度 \t"+" 空闲");
for (Used used : usedList) {
System.out.println(used+"\t");
}
}
public static void free(){
frees.clear();
int no=1;
for(int i=1;i<=addrNum.size();i++){
if(2*i+1<addrNum.size()){
if(addrNum.get(2*i-1)-addrNum.get(2*i)!=-1){
frees.add(new Free(no,"---",addrNum.get(2*i-1)+1,addrNum.get(2*i)-1,true));
no++;
}
}
}
System.out.println("-------------------------------------空闲分区表--------------------------------------");
System.out.println(" No \t"+"进行名 \t"+"起始地址 \t"+"结束地址 \t"+" 长度 \t"+" 空闲");
for (Free free : frees) {
System.out.println(free+"\t");
}
addrNum.clear();
}
public static void main(String[] args) {
BestFit.init();
do {
System.out.println();
System.out.println("------------------------------请选择要进行的操作-----------------------------------");
System.out.println("0:退出系统 1:查看内存使用情况 2:添加进程到内存 3:回收进程");
System.out.print("请选择:");
int n = new Scanner(System.in).nextInt();
switch (n){
case 1:
BestFit.used
();
BestFit.free();
break;
case 2:
System.out.print("请输入进程名:");
String name = new Scanner(System.in).next();
System.out.print("请输入进程大小:");
int size = new Scanner(System.in).nextInt();
BestFit.addProcess(name,size);
break;
case 3:
System.out.print("进程回收 输入进程名:");
String pName = new Scanner(System.in).next();
BestFit.recycleProcess(pName);
break;
case 0:
return;
}
}while (true);
}
}
文字描述
运行截图:
实验三:文件系统仿真
实验目的
件系统是操作系统中用来存储和管理信息的机构,它具有按名存取的功能。不仅方便用户使用,而且能提高系统效率,信息安全可靠。 在用户程序中通过使用文件系统提供的一整套命令,如:创建、打开、读、写、关闭、删除等文件命令,对文件进行操作。 实体类 File类
package com.xu.demo.ytu.filesystem;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class File {
private String fileName;
private int protect;
private int size;
private ArrayList<Integer> address;
private boolean state;
private boolean read;
private boolean write;
public File(String fileName, int protect, int size, ArrayList<Integer> address) {
this.fileName = fileName;
this.protect = protect;
this.size = size;
this.address = address;
}
@Override
public String toString() {
return
" " + fileName +"\t"+
" " + protect+"\t"+
" " + size+"\t"+
" " + address +"\t";
}
}
MFD类
package com.xu.demo.ytu.filesystem;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MFD {
private String userName;
private String address;
private UFD ufd;
@Override
public String toString() {
return
" " + userName +"\t"+
" " + address +"\t";
}
}
UFD类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UFD {
private String address;
private List<File> fileList;
private List<UOF> uofList;
}
UOF类
package com.xu.demo.ytu.filesystem;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UOF {
private String fileName;
private int protect;
private Boolean state;
private Boolean read;
private Boolean write;
@Override
public String toString() {
return
" " + fileName +"\t"+
" " + protect +"\t"+
" " + state +"\t"+
" " + read +"\t"+
" " + write +"\t";
}
}
具体实现 FileSystem
package com.xu.demo.ytu.filesystem;
import java.util.*;
public class FileSystem {
;
public static List<MFD> mfdList = new ArrayList<>(4);
public static int[] capacity = new int[100];
public static void init() {
System.out.println("---------------------------------文件系统基本操作----------------------------------------------------");
System.out.print("create:创建文件\t");
System.out.print(" open: 打开文件\t");
System.out.print(" close: 关闭文件\t");
System.out.print(" read: 读操作\t");
System.out.println(" write: 写操作\t");
System.out.print("delete: 删除文件\t");
System.out.print(" cd: 返回根目录\t");
System.out.print(" exit: 退出系统\t");
System.out.print(" 保护: 1: 可读 2: 可写 3:可读可写\t");
System.out.println();
mfdList.add(new MFD("xu-01", "001", new UFD("001", new ArrayList<>(), new ArrayList<>())));
mfdList.add(new MFD("xu-02", "002", new UFD()));
mfdList.add(new MFD("xu-03", "003", new UFD()));
mfdList.add(new MFD("xu-04", "004", new UFD()));
System.out.println("一级目录");
System.out.println(" 文件夹名" + " \t文件地址");
for (MFD mfd : mfdList) {
System.out.println(mfd);
}
for (MFD mfd : mfdList) {
if (mfd.getAddress().equals("001")) {
mfd.getUfd().setAddress(mfd.getAddress());
List<File> fileList = new ArrayList<>();
ArrayList<Integer> address01 = new ArrayList<>();
address01.add(0);
address01.add(1);
address01.add(2);
ArrayList<Integer> address02 = new ArrayList<>();
address02.add(3);
address02.add(4);
fileList.add(new File("file01", 1, 3, address01));
fileList.add(new File("file02", 2, 2, address02));
mfd.getUfd().setFileList(fileList);
for (int i = 0; i < 100; i++) {
if (i < 5) {
capacity[i] = 1;
} else {
capacity[i] = 10;
}
}
return;
}
}
}
public static void show(MFD mfd) {
System.out.println("-------------------------------文件列表----------------------------------------");
System.out.println(" 文件名" + " 保护程度" + " 文件大小" + " 文件地址");
for (File file : mfd.getUfd().getFileList()) {
mfd.getUfd().getUofList().add(new UOF(file.getFileName(), file.getProtect(), file.isState(), file.isRead(), file.isWrite()));
System.out.println(file);
}
System.out.println("---------------------------------UOF表-----------------------------------------");
System.out.println(" 文件名" + " 保护程度" + " 是否打开" + " 读指针" + " 写指针");
for (UOF uof : mfd.getUfd().getUofList()) {
System.out.println(uof);
}
mfd.getUfd().getUofList().clear();
}
public static List<Integer> findAddress(int fileSize) {
List<Integer> temList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
if (capacity[i] == 10) {
for (int j = i; j < fileSize + i; j++) {
if (j >= 100) {
return null;
}
temList.add(capacity[j]);
}
if (temList.contains(1)) {
temList.clear();
} else {
temList.clear();
int realAddress = i;
for (int n = 0; n < fileSize; n++) {
temList.add(realAddress);
capacity[realAddress] = 1;
realAddress++;
}
return temList;
}
}
}
return temList;
}
public static void clearAddress(int startAddress, int fileSize) {
for (int i = startAddress; i <= startAddress+fileSize; i++) {
capacity[i] = 10;
}
}
public static void create(MFD mfd, String fileName, int fileProtect, int fileSize) {
for (File file : mfd.getUfd().getFileList()) {
if (file.getFileName().equals(fileName)) {
System.out.println("该文件已经存在!!!无法创建!!!");
return;
}
}
File file = new File(fileName, fileProtect, fileSize, new ArrayList<>());
List<Integer> address = FileSystem.findAddress(fileSize);
if (address == null||address.size()==0) {
System.out.println("存储空间不足!!操作执行失败!!!");
return;
}
file.setAddress((ArrayList<Integer>) address);
mfd.getUfd().getFileList().add(file);
}
public static void write(MFD mfd, String fileName, int fileProtect, int fileSize) {
for (File file : mfd.getUfd().getFileList()) {
if (file.getFileName().equals(fileName)) {
if (file.getProtect() == 1) {
System.out.println("该文件是只是可读文件!!无法进行写操作!!!");
return;
}
if (file.isState()) {
FileSystem.clearAddress(file.getAddress().get(0), file.getSize());
file.setProtect(fileProtect);
List<Integer> address = FileSystem.findAddress(fileSize);
if (address == null||address.size()==0) {
System.out.println("存储空间不足!!操作执行失败!!!");
return;
}
file.setAddress((ArrayList<Integer>) address);
file.setWrite(true);
} else {
System.out.println("文件未打开,无法操作!!!");
}
return;
}
}
System.out.println("文件不存在无法执行写操作!!!");
}
public static void open(MFD mfd, String fileName) {
for (File file : mfd.getUfd().getFileList()) {
if (file.getFileName().equals(fileName)) {
file.setState(true);
return;
}
}
System.out.println("该文件不存在!!无法打开!!!");
}
public static void close(MFD mfd, String fileName) {
for (File file : mfd.getUfd().getFileList()) {
if (file.getFileName().equals(fileName)) {
if (!file.isState()) {
System.out.println("文件未打开!!不用关闭!!!");
return;
}
file.setState(false);
file.setRead(false);
file.setWrite(false);
return;
}
}
System.out.println("该文件不存在!!无法关闭!!!");
}
public static void read(MFD mfd, String fileName) {
for (File file : mfd.getUfd().getFileList()) {
if (file.getFileName().equals(fileName)) {
if (!file.isState()) {
System.out.println("文件未打开!!无法进行读操作!!!");
return;
}
if (file.getProtect() == 2) {
System.out.println("该文件是只是可写的!!无法进行读操作!!!");
return;
}
file.setRead(true);
return;
}
}
System.out.println("该文件不存在!!无法进行读操作!!!");
}
public static void delete(MFD mfd, String fileName) {
for (File file : mfd.getUfd().getFileList()) {
if (file.getFileName().equals(fileName)) {
FileSystem.clearAddress(file.getAddress().get(0), file.getSize());
mfd.getUfd().getFileList().remove(file);
return;
}
}
System.out.println("该文件不存在!!无法删除!!!");
}
public static void operation(String instruct, MFD mfd) {
String[] ins = instruct.split(" ");
String n = ins[0];
switch (n) {
case "create":
FileSystem.create(mfd, ins[1], Integer.parseInt(ins[2]), Integer.parseInt(ins[3]));
FileSystem.show(mfd);
break;
case "write":
FileSystem.write(mfd, ins[1], Integer.parseInt(ins[2]), Integer.parseInt(ins[3]));
FileSystem.show(mfd);
break;
case "open":
FileSystem.open(mfd, ins[1]);
FileSystem.show(mfd);
break;
case "close":
FileSystem.close(mfd, ins[1]);
FileSystem.show(mfd);
break;
case "read":
FileSystem.read(mfd, ins[1]);
FileSystem.show(mfd);
break;
case "delete":
FileSystem.delete(mfd, ins[1]);
FileSystem.show(mfd);
break;
case "cd":
FileSystem.enterFolder();
break;
}
}
public static String enterFolder() {
System.out.print("请选择你要进入的目录:");
String folderName = new Scanner(System.in).next();
for (MFD mfd : mfdList) {
if (mfd.getUserName().equals(folderName)) {
if (mfd.getUfd().getFileList() != null) {
FileSystem.show(mfd);
do {
System.out.print("filesystem:/" + mfd.getUserName() + "/:");
String in = new Scanner(System.in).nextLine();
if (in.equals("exit")) return "文件系统运行结束";
FileSystem.operation(in, mfd);
} while (true);
} else {
System.out.println("该目录没有文件请操作");
mfd.getUfd().setAddress(mfd.getAddress());
mfd.getUfd().setUofList(new ArrayList<>());
mfd.getUfd().setFileList(new ArrayList<>());
do {
System.out.print("filesystem:/" + mfd.getUserName() + "/:");
String in = new Scanner(System.in).nextLine();
if (in.equals("exit")) return "文件系统运行结束";
FileSystem.operation(in, mfd);
} while (true);
}
}
}
if (folderName.equals("exit")) return "文件系统运行结束";
System.out.println("目录不存在!!!");
FileSystem.enterFolder();
return "目录不存在";
}
public static void main(String[] args) {
FileSystem.init();
System.out.println(FileSystem.enterFolder());
}
}
文字描述
运行截图
|