进程与资源管理实验
框架设计
- main类,是程序的Test Shell,主要实现了读取命令、语句转换和显示结果等功能。
- PCB(进程管理块)类,用于进程的管理, 主要实现了进程的创建、进程的切换与调度以及进程信息的输出等功能。
- Process类,定义了进程的数据结构,主要实现了删除进程、递归删除子进程树、销毁所有进程等功能。
- Resource类,定义了资源的数据结构,主要实现了请求资源、释放资源、输出资源信息等功能。另外,该类对每一个资源管理和维护了对应的阻塞队列,当进程请求资源不足时,将进程加入对应的阻塞队列中。
- Queue类,用于管理和维护进程队列,主要实现了3种优先级队列的入队、出队、删除等操作。
具体实现
main.java
import java.io.*;
import java.util.Scanner;
/**
* @BelongsProject:OS-process
* @BelongsPackage:PACKAGE_NAME
* @Author:Uestc_Xiye
* @CreateTime:2020-12-01 16:53:00
*/
public class main {
private static final Pcb pcb=Pcb.getpcb();
private static final Resource r1=new Resource(1,1);
private static final Resource r2=new Resource(2,2);
private static final Resource r3=new Resource(3,3);
private static final Resource r4=new Resource(4,4);
public static void main(String[] args) throws IOException
{
pcb.createProcess("init",0);
System.out.print("init"+" ");
if(args.length!=0)
{
loadFile(args[0]);
}
else
{
System.out.println();
Scanner scanner=new Scanner(System.in);
while(scanner.hasNextLine())
{
String input=scanner.nextLine();
if(input.trim().equals(""))
{
continue;
}
testShell(input);
}
}
}
public static void testShell(String input)
{
String[] commands=new String[]{input};
for(String command:commands)
{
String[] cmds=command.split("\\s+");
String options=cmds[0];
switch(options)
{
case "cr":
if (cmds.length!=3)
{
System.out.println("Error! Please enter the legal parameters!");
}
else
{
String processName=cmds[1];
int priority=0;
try
{
priority=Integer.parseInt(cmds[2]);
if(priority<=0 || priority>2)
{
System.out.println("Error!Please enter the legal parameters!");
continue;
}
} catch (Exception e) {System.out.println("Error!Please enter the legal parameters!");}
if(pcb.isExistName(processName))
{
System.out.println("Error!Process "+processName+"already exists!Please select another process name!");
break;
}
pcb.createProcess(processName,priority);
}
break;
case "de":
if(cmds.length!=2)
{
System.out.println("Error!Please enter the legal parameters!");
}
else
{
String processName=cmds[1];
Process process = pcb.findProcess(processName);
if(process==null)
{
System.out.println("Error!Process " + processName + "does not exist!");
}
else if(processName.equals("init"))
{
System.out.println("Error!You do not have permission to terminate the init process!");
}
else
{
process.destroy();
}
}
break;
case "req":
if(cmds.length!=3)
{
System.out.println("Error!Please enter the legal parameters!");
}
else
{
String resourceName=cmds[1];
int need=0;
try
{
need=Integer.parseInt(cmds[2]);
} catch (Exception e) {System.out.println("Error!Please enter the legal parameters!");}
Process currentProcess=pcb.getcurrentProcess();
switch(resourceName)
{
case "R1":
r1.requestResource(currentProcess,need);
break;
case "R2":
r2.requestResource(currentProcess,need);
break;
case "R3":
r3.requestResource(currentProcess,need);
break;
case "R4":
r4.requestResource(currentProcess,need);
break;
default:
System.out.println("Error!Please enter the legal parameters!");
}
}
break;
case "rel":
if(cmds.length!=3)
{
System.out.println("Error!Please enter the legal parameters!");
}
else
{
String resourceName=cmds[1];
int rel=0;
try
{
rel=Integer.parseInt(cmds[2]);
} catch (Exception e) {System.out.println("Error!Please enter the legal parameters!");}
Process currentProcess = pcb.getcurrentProcess();
switch(resourceName)
{
case "R1":
r1.releaseResource(currentProcess,rel);
break;
case "R2":
r2.releaseResource(currentProcess,rel);
break;
case "R3":
r3.releaseResource(currentProcess,rel);
break;
case "R4":
r4.releaseResource(currentProcess,rel);
break;
default:
System.out.println("Error!Please enter the legal parameters!");
}
}
break;
case "to":
pcb.timeout();
break;
case "lp":
if(cmds.length==1)
{
pcb.printProcessTree(pcb.findProcess("init"),0);
}
else if(cmds.length<3 || !cmds[1].equals("-p"))
{
System.out.println("Error!Please enter a legal parameter or command!");
}
else
{
String pName=cmds[2];
Process process=pcb.findProcess(pName);
if(process==null)
{
System.out.println("Error!Process "+pName+"does not exist!");
}
else
{
pcb.printProcessDetail(process);
}
}
break;
case "lr":
r1.printStatus();
r2.printStatus();
r3.printStatus();
r4.printStatus();
break;
case "exit":
System.out.println("Bye!");
System.exit(0);
case "list":
pcb.printExistProcess();
break;
default:
System.out.println("Error!Please enter the legal command!");
break;
}
}
if(pcb.getcurrentProcess()!=null)
{
System.out.print(pcb.getcurrentProcess().getpName()+" ");
}
}
private static void loadFile(String filePath) throws IOException
{
InputStream inputStream=new FileInputStream(filePath);
LineNumberReader lineNumberReader=new LineNumberReader(new FileReader(filePath));
String cmd=null;
while((cmd=lineNumberReader.readLine())!=null)
{
if(!"".equals(cmd))
{
testShell(cmd);
}
}
}
}
Pcb.java
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @BelongsProject:OS-process
* @BelongsPackage:PACKAGE_NAME
* @Author:Uestc_Xiye
* @CreateTime:2020-12-01 16:52:29
*/
public class Pcb {
/**
* 变量说明
* pcb: 进程控制块(Process Control Block)
* readyQueue: 就绪队列
* existProcess: 所有存活的进程,包括Running(运行状态),Blocked(阻塞状态),Ready(就绪状态)
* currentProcess: 当前正在占用CPU的进程
* pidGenerator: pid生成器,可以生成唯一的pid
*/
private static final Pcb pcb=new Pcb();
private static final Queue readyQueue=Queue.getreadyQueue();
private static Map<String,Process> existProcess;
private Process currentProcess;
private AtomicInteger pidGenerator;
private Pcb()
{
existProcess=new HashMap<>();
pidGenerator=new AtomicInteger();
}
public Process createProcess(String processName,int priority)
{
Process currentProcess=pcb.getcurrentProcess();
// 为新建进程分配pid,进程名,优先级,进程状态,资源,父进程和子进程等信息
Process process=new Process(pcb.createpid(),processName,priority,Process.State.NEW,new ConcurrentHashMap<>(),currentProcess,new LinkedList<>());
if(currentProcess!=null)
{
currentProcess.getchildren().add(process);
process.setparent(currentProcess);
}
pcb.addexistProcess(process);
readyQueue.addprocess(process);
process.setstate(Process.State.READY);
Pcb.scheduler();
return process;
}
public static void scheduler()
{
Process currentProcess=pcb.getcurrentProcess();
Process readyProcess=readyQueue.getprocess();
if(readyProcess==null)
{
pcb.getcurrentProcess().setstate(Process.State.RUNNING);
return;
}
else if(currentProcess==null)
{
readyQueue.deleteProcess(readyProcess);
pcb.setcurrentProcess(readyProcess);
readyProcess.setstate(Process.State.RUNNING);
return;
}
else if(currentProcess.getstate()==Process.State.BLOCKED || currentProcess.getstate()==Process.State.TERMINATED)
{
readyQueue.deleteProcess(readyProcess);
pcb.setcurrentProcess(readyProcess);
readyProcess.setstate(Process.State.RUNNING);
}
else if(currentProcess.getstate()==Process.State.RUNNING)
{
if(currentProcess.getpriority()<readyProcess.getpriority())
{
preempt(readyProcess,currentProcess);
}
}
else if(currentProcess.getstate()==Process.State.READY)
{
if(currentProcess.getpriority()<=readyProcess.getpriority())
{
preempt(readyProcess,currentProcess);
}
else
{
currentProcess.setstate(Process.State.RUNNING);
}
}
return;
}
public static void preempt(Process readyProcess,Process currentProcess)
{
if(isExistName(currentProcess.getpName()))
{
readyQueue.addprocess(currentProcess);
currentProcess.setstate(Process.State.READY);
readyQueue.deleteProcess(readyProcess);
pcb.setcurrentProcess(readyProcess);
readyProcess.setstate(Process.State.RUNNING);
return;
}
}
public static void timeout()
{
pcb.getcurrentProcess().setstate(Process.State.READY);
scheduler();
}
public void deleteexistProcess(Process process)
{
String name=process.getpName();
existProcess.remove(name);
}
public void printProcessTree(Process process,int retract)
{
for (int i=0;i<retract;i++)
{
System.out.print(" ");
}
System.out.print("|-");
printProcessDetail(process);
List<Process> children=process.getchildren();
for(Process child:children)
{
printProcessTree(child,retract+1);
}
}
public void printProcessDetail(Process process)
{
System.out.print(process.getpName()+"(PID:"+process.getpid()+",进程状态:"+process.getstate()+",优先级:"+process.getpriority() + ",");
if(process.getresourceMap().isEmpty())
{
System.out.println("(无资源占用))");
}
else
{
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("(");
for(Map.Entry<Resource,Integer> entry:process.getresourceMap().entrySet())
{
Resource res=entry.getKey();
int holdNum=entry.getValue();
stringBuilder.append(",")
.append("R")
.append(res.getrid())
.append(":")
.append(holdNum);
}
stringBuilder.append(")");
String result=stringBuilder.toString();
System.out.println(result.replaceFirst(",",""));
}
}
public void printExistProcess()
{
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("existList:[");
for(Map.Entry<String,Process> entry:existProcess.entrySet())
{
String name=entry.getKey();
String state=entry.getValue().getstate().toString();
stringBuilder.append(",")
.append(name)
.append("(")
.append(state)
.append(")");
}
stringBuilder.append("]");
String result=stringBuilder.toString();
System.out.println(result.replaceFirst(",", ""));
}
public int createpid()
{
return pidGenerator.getAndIncrement();
}
public void addexistProcess(Process process)
{
existProcess.put(process.getpName(),process);
}
public static boolean isExistName(String name)
{
return existProcess.containsKey(name);
}
public Process findProcess(String processName)
{
for(Map.Entry<String, Process> entry:existProcess.entrySet())
{
if(processName.equals(entry.getKey()))
{
return entry.getValue();
}
}
return null;
}
public void deleteProcess(Process process)
{
}
public void setcurrentProcess(Process currentProcess)
{
this.currentProcess=currentProcess;
}
public void setPidGenerator(AtomicInteger pidGenerator)
{
this.pidGenerator=pidGenerator;
}
public static Pcb getpcb()
{
return pcb;
}
public Queue getreadyQueue()
{
return readyQueue;
}
public Map<String,Process> getexistProcess()
{
return existProcess;
}
public Process getcurrentProcess()
{
return currentProcess;
}
public AtomicInteger getPidGenerator()
{
return pidGenerator;
}
}
Process.java
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @BelongsProject:OS-process
* @BelongsPackage:PACKAGE_NAME
* @Author:Uestc_Xiye
* @CreateTime:2020-12-01 16:52:02
*/
public class Process {
/**
* 变量说明
* pid: 进程的id,唯一
* pName: 进程的名字
* priority: 进程的优先级
* state: 进程的状态,有五种,具体见于State中
* blockedResource: 如果进程状态为阻塞的话,这个属性指向被阻塞的资源,否则为NULL
* resourceMap: 进程持有的资源和相应数量
* parent: 进程的父进程
* children: 进程的子进程(们)
*/
private int pid;
private String pName;
private int priority;
private State state;
private Resource blockedResource;
private ConcurrentHashMap<Resource,Integer> resourceMap;
private Process parent;
private List<Process> children;
private static final Pcb pcb=Pcb.getpcb();
private static final Queue readyQueue=Queue.getreadyQueue();
/**
* 进程的五种状态
* NEW: 新建状态
* READY: 就绪状态
* RUNNING: 执行状态
* BLOCKED: 阻塞状态
* TERMINATED: 终止状态
*/
public enum State
{
NEW,READY,RUNNING,BLOCKED,TERMINATED
}
public Process(int pid,String pName,int priority,State state,ConcurrentHashMap<Resource,Integer> resourceMap,Process parent,List<Process> children)
{
this.pid=pid;
this.pName=pName;
this.priority=priority;
this.state=state;
this.resourceMap=resourceMap;
this.parent=parent;
this.children=children;
}
public void deleteChild(Process process)
{
for(Process child:children)
{
if(child==process)
{
children.remove(child);
return;
}
}
}
public void deleteProcessTree()
{
if(!children.isEmpty())
{
for(int i=0;i<children.size();i++)
{
Process child=children.get(0);
child.deleteProcessTree();// 递归删除子树
}
}
// 对不同状态的进程处理
// 若进程状态为终止状态,说明删除成功
if(this.getstate()==State.TERMINATED)
{
pcb.deleteProcess(this);
return;
}
// 若进程状态为就绪状态,则从就绪队列删除,修改其状态为终止状态
else if(this.getstate()==State.READY)
{
readyQueue.deleteProcess(this);
pcb.deleteProcess(this);
this.setstate(State.TERMINATED);
}
// 若进程状态为阻塞状态,则从阻塞队列删除,修改其状态为终止状态
else if(this.getstate()==State.BLOCKED)
{
Resource blockedResource=this.getblockedResource();
blockedResource.deleteblockedProcess(this);
pcb.deleteProcess(this);
this.setstate(State.TERMINATED);
}
// 若进程状态为运行状态时直接终止,则修改其状态为终止状态
else if(this.getstate()==State.RUNNING)
{
pcb.deleteProcess(this);
this.setstate(State.TERMINATED);
}
// 清除进程的parent和child指针
parent.deleteChild(this);
parent=null;
// 释放资源
for(Resource resource:resourceMap.keySet())
{
resource.releaseResource(this);
}
return;
}
public void destroy()
{
deleteProcessTree();
Pcb.scheduler();
return;
}
public void setpid(int pid)
{
this.pid=pid;
}
public void setpName(String pName)
{
this.pName=pName;
}
public void setpriority(int priority)
{
this.priority=priority;
}
public void setstate(State state)
{
this.state=state;
}
public void setblockedResource(Resource blockedResource)
{
this.blockedResource=blockedResource;
}
public void setrMap(ConcurrentHashMap<Resource,Integer> resourceMap)
{
this.resourceMap=resourceMap;
}
public void setparent(Process parent)
{
this.parent=parent;
}
public void setchildren(List<Process> children)
{
this.children=children;
}
public int getpid()
{
return pid;
}
public String getpName()
{
return pName;
}
public int getpriority()
{
return priority;
}
public State getstate()
{
return state;
}
public Resource getblockedResource()
{
return blockedResource;
}
public ConcurrentHashMap<Resource,Integer> getresourceMap()
{
return resourceMap;
}
public Process getparent()
{
return parent;
}
public List<Process> getchildren()
{
return children;
}
}
Resource.java
import java.util.Deque;
import java.util.LinkedList;
import java.util.Map;
/**
* @BelongsProject:OS-process
* @BelongsPackage:PACKAGE_NAME
* @Author:Uestc_Xiye
* @CreateTime:2020-12-01 16:51:48
*/
public class Resource {
/**
* 变量说明
* rid: 资源的id,唯一
* maxResource: 资源的最大数量
* remainingResource: 剩余的资源的数量
* blockedDeque: 在一个资源上阻塞的进程队列
*/
private int rid;
private int maxResource;
private int remainingResource;
private Deque<BlockedProcess> blockedDeque;
private static final Pcb pcb=Pcb.getpcb();
private static final Queue readyQueue=Queue.getreadyQueue();
public class BlockedProcess
{
/**
* 变量说明
* process: 进程
* need: 需要请求的资源数量
*/
private Process process;
private int need;
public BlockedProcess(Process process,int need)
{
this.process=process;
this.need=need;
}
public void setprocess(Process process)
{
this.process=process;
}
public void setneed(int need)
{
this.need=need;
}
public Process getprocess()
{
return process;
}
public int getneed()
{
return need;
}
}
public Resource(int rid,int maxResource)
{
this.rid=rid;
this.maxResource=maxResource;
this.remainingResource=maxResource;
blockedDeque=new LinkedList<>();
}
public void addremainingResource(int num)
{
this.remainingResource+=num;
}
public void deleteblockedProcess(Process process)
{
for(BlockedProcess blockedProcess:blockedDeque)
{
if(blockedProcess.getprocess()==process)
{
blockedDeque.remove(blockedProcess);
}
}
}
public void requestResource(Process process,int need)
{
// 若请求数量大于最大数量,则请求失败
if(need>maxResource)
{
System.out.println("Request Resource Failed!");
return;
}
// 对于非init进程,将该进程加入阻塞队列,并设置进程为阻塞状态
else if(need>remainingResource && !"init".equals(process.getpName()))
{
blockedDeque.addLast(new BlockedProcess(process,need));
process.setstate(Process.State.BLOCKED);
process.setblockedResource(this);
Pcb.scheduler();
return;
}
// 对于init进程,不阻塞
else if(need>remainingResource && "init".equals(process.getpName()))
{
return;
}
// 若可以正常分配资源,则剩余资源的数量减少,已分配资源的数量增加
else
{
remainingResource-=need;
Map<Resource,Integer> resourceMap=process.getresourceMap();
if(resourceMap.containsKey(this))
{
Integer alreadyNum=resourceMap.get(this);
resourceMap.put(this,alreadyNum+need);
}
else
{
resourceMap.put(this,need);
}
}
}
public void releaseResource(Process process)
{
int num=0;
num=process.getresourceMap().remove(this);
if(num==0)
{
return;
}
remainingResource+=num;
while(!blockedDeque.isEmpty())
{
BlockedProcess blockedProcess = blockedDeque.peekFirst();
int need=blockedProcess.getneed();
// 若剩余资源数量大于need,则唤醒阻塞队列队头的一个进程
if(remainingResource>= need)
{
Process readyProcess=blockedProcess.getprocess();
requestResource(readyProcess,need);
blockedDeque.removeFirst();
readyQueue.addprocess(readyProcess);
readyProcess.setstate(Process.State.READY);
readyProcess.setblockedResource(null);
// 若唤醒的进程优先级高于当前进程优先级,则抢占执行
if(readyProcess.getpriority()>pcb.getcurrentProcess().getpriority())
{
pcb.preempt(readyProcess,pcb.getcurrentProcess());
}
}
else
{
break;
}
}
}
public void releaseResource(Process process,int num)
{
if(num==0)
{
return;
}
remainingResource+=num;
while(!blockedDeque.isEmpty())
{
BlockedProcess blockedProcess = blockedDeque.peekFirst();
int need=blockedProcess.getneed();
// 若剩余资源数量大于need,则唤醒阻塞队列队头的一个进程
if(remainingResource>= need)
{
Process readyProcess=blockedProcess.getprocess();
requestResource(readyProcess,need);
blockedDeque.removeFirst();
readyQueue.addprocess(readyProcess);
readyProcess.setstate(Process.State.READY);
readyProcess.setblockedResource(null);
// 若唤醒的进程优先级高于当前进程优先级,则抢占执行
if(readyProcess.getpriority()>pcb.getcurrentProcess().getpriority())
{
pcb.preempt(readyProcess,pcb.getcurrentProcess());
}
}
else
{
break;
}
}
}
public void printStatus()
{
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("resource-").append(rid)
.append("{maxResource=").append(maxResource)
.append(",remainingResource:").append(remainingResource)
.append(",")
.append("blockedDeque[");
for(BlockedProcess bProcess:blockedDeque)
{
stringBuilder.append(",{")
.append(bProcess.getprocess().getpName())
.append(":")
.append(bProcess.getneed())
.append("}");
}
stringBuilder.append("]}");
String result=stringBuilder.toString();
System.out.println(result.replace("[,", "["));
}
public void setrid(int rid)
{
this.rid=rid;
}
public void setmaxResource(int maxResource)
{
this.maxResource=maxResource;
}
public void setremainingResource(int remainingResource)
{
this.remainingResource=remainingResource;
}
public void setblockedDeque(Deque<BlockedProcess> blockedDeque)
{
this.blockedDeque=blockedDeque;
}
public int getrid()
{
return rid;
}
public int getmaxResource()
{
return maxResource;
}
public int getremainingResource()
{
return remainingResource;
}
public Deque<BlockedProcess> getblockedDeque()
{
return blockedDeque;
}
}
Queue.java
import java.util.Deque;
import java.util.LinkedList;
/**
* @BelongsProject:OS-process
* @BelongsPackage:PACKAGE_NAME
* @Author:Uestc_Xiye
* @CreateTime:2020-12-01 16:51:38
*/
public class Queue {
/**
* deque: 不同优先级就绪队列组成数组
* readyQueue: 就绪队列
*/
private Deque<Process>[] deque;
private static final Queue readyQueue=new Queue();
private Queue()
{
//因为进程有3种不同优先级,所以构造3个就绪队列
deque=new LinkedList[3];
for(int i=0;i<3;i++)
{
deque[i]=new LinkedList<>();
}
}
public void addprocess(Process process)
{
int priority=process.getpriority();
Deque<Process> d=deque[priority];
d.addLast(process);
}
public boolean deleteProcess(Process process)
{
int priority = process.getpriority();
Deque<Process> d=deque[priority];
return d.remove(process);
}
public static Queue getreadyQueue()
{
return readyQueue;
}
public Process getprocess()
{
for (int i=2;i>=0;i--)
{
Deque<Process> d=deque[i];
if(!d.isEmpty())
{
return d.peekFirst();
}
}
return null;
}
}
把上述五个程序打包成Jar,打包方法见于IntelliJ IDEA 2020.1.3 封装jar包的方法及两个错误示例。
之后把实验数据与Jar放在同一目录下,在cmd调用下面的命令即可运行。
java -jar *.jar *.txt
虚拟内存综合实验
运行Bochs-2.5.1.exe,安装Bochs虚拟机。安装完成后,复制下列文件至安装根目录。
运行bochsdbg.exe,点击Load加载mybochssrc-hd.bxrc文件,再点击Start启动Bochs虚拟机。
Bochs虚拟机启动后,会出现两个窗口:Console窗口和Display窗口,如图17所示。Console窗口为Bochs命令输入窗口,Display窗口为Linux操作系统窗口。
在Console窗口输入命令:c,加载Linux操作系统。
继续输入命令:vi test.c,加载实验程序,输入命令: :wq,保存程序并退出。
输入命令:gcc -o test test.c编译程序,再输入命令:./test运行程序。
可以看出,程序运行至while(j)语句时,进入了死循环,所以没有继续运行后面的语句。
在Console窗口按下Ctrl+C,中断运行,输入sreg,查看段的具体信息。