实验5 进程管理模拟

  • 格式:doc
  • 大小:74.00 KB
  • 文档页数:10

实验5 进程管理模拟一、实验目的进程是操作系统中最核心的概念,是了解操作系统实质的关键。

本实验的目在于:加深对进程概念的理解;熟悉操作系统在管理进程时所采用的数据结构;掌握基本的进程状态及其转换;熟悉主要的进程调度算法。

二、实验要求设计一个允许n个进程并发执行的进程管理模拟系统。

该系统具有以下功能:(1)建立良好的数据结构实现对进程的有效管理(2)进程控制功能(3)进程调度(4)显示进程执行期间状态的变化。

系统在模拟时,可将各进程对资源的使用情况直接以数据的形式输入或者随机生成。

三、实验环境Linux C四、范例(使用Visual C++ 6.0)为了体现计算机在运行时各设备可以并行工作,本例设置了三个线程CPU_Thread、IO1_Thread、IO2_Thread分别模拟三个设备。

在通过调度程序Scheduler(线程)调度,多个进程根据各自的资源使用情况可同时在这三个设备上穿插运行。

#include "stdafx.h"#define STRICT#define WIN32_LEAN_AND_MEAN#include "iostream.h"#include <windows.h>#include <winbase.h>#include <stdio.h>#include <stdlib.h>#include <time.h>extern "C"#define MAXPCBCOUNT 20#define MAXRESCOUNT 1000#define TIMESLICE 10//定义进程的基本状态typedef enum ProcStatus{ PS_READY=0, PS_RUN=1 , PS_BLOCK=-1 } PROC_STA TUS;typedef enum ResourceID //系统中资源的编号,系统只有1CPU,及I/O设备IO1,IO2{ RES_CPU=1, RES_IO1=2, RES_IO2=3 } RESOURCE_ID;typedef struct ResNode //资源结点{ RESOURCE_ID ResID; //资源IDunsigned int Time; //使用时间int Next;}RESNODE;//定义PCB的组成typedef struct PCBNode{//Part1:进程标识符及名称int PID;char Name[256];//Part2:处理机现场信息。

unsigned long Reg1; //通用寄存器1,unsigned long Reg2; //通用寄存器2,Reg3—Reg8略去unsigned long PC; //指令计数器PCunsigned long PSW; //程序状态字//Part3:进程的调度信息PROC_STATUS Status; //进程状态int Priority; //进程优先级//Part4:进程的控制信息int PreProc; //链接指针,前驱int NextProc; //链接指针,后继int CodeAddr ;int DataAddr ;}PCB;PCB PCBTable[MAXPCBCOUNT]; //定义了PCB表RESNODE RESTable[MAXRESCOUNT]; //定义了资源表int ProcCount ; //当前系统中进程总数int ResHead_Free; //资源表空间链表的头指针int Head_Free; //空闲空间链表的头指针int Head_Ready; //就绪队列头指针int Head_Run; //运行队列头指针int Head_Block1; //IO1的阻塞队列头指针int Head_Block2; //IO2的阻塞队列头指针HANDLE hSystem[4]; //系统线程Handle,0-3分别是调度进程Scheduler,CPU,IO1,IO2 unsigned long PC ; //存储进程的执行位置unsigned long Reg1; //用来资源类型unsigned long Reg2; //用来使用时间int NewPCB(void) //申请PCB空间{ int nPos;if (Head_Free!=-1 ){ nPos=Head_Free;Head_Free=PCBTable[Head_Free].NextProc;}elsenPos= -1;return nPos;}void FreePCB(int nPos) //释放给定的PCB空间{if(nPos>=0 && nPos<MAXPCBCOUNT){ PCBTable[nPos].NextProc=Head_Free;Head_Free=nPos;}}int NewRES(void) //申请资源空间{ int nPos;if (ResHead_Free!=-1 ){ nPos=ResHead_Free;ResHead_Free=RESTable[ResHead_Free].Next;}elsenPos= -1;return nPos;}void FreeRES(int nPos) //释放给定的资源空间{if(nPos>=0 && nPos<MAXRESCOUNT){ RESTable[nPos].Next=ResHead_Free;ResHead_Free=nPos;}}void AddtoQueue(int *Head, int nPos) //将给定的进程加入到给定队列的末尾{ int nPosPre;if( *Head==-1 ){ PCBTable[nPos].NextProc=-1;PCBTable[nPos].PreProc=-1;*Head=nPos;}else{ nPosPre=*Head;while( PCBTable[nPosPre].NextProc!=-1 )nPosPre=PCBTable[nPosPre].NextProc;PCBTable[nPosPre].NextProc=nPos;PCBTable[nPos].PreProc=nPosPre;PCBTable[nPos].NextProc=-1;}}void Block(int pcbID , RESOURCE_ID ResID ){ //保存该进程的CPU现场PCBTable[pcbID].Reg1=Reg1;PCBTable[pcbID].Reg2=Reg2;PCBTable[pcbID].PC=PC;PCBTable[pcbID].Status=PS_BLOCK;if(ResID==RES_IO1) //根据其阻塞的原因,将其插入到相应的阻塞队列中{ AddtoQueue(&Head_Block1, pcbID);cout<<"进程:"<<PCBTable[pcbID].PID<<" "<<PCBTable[pcbID].Name<<"进入阻塞队列1!"<<endl;ResumeThread(hSystem[2]);}else{ AddtoQueue(&Head_Block2, pcbID);cout<<"进程:"<<PCBTable[pcbID].PID<<" "<<PCBTable[pcbID].Name<<"进入阻塞队列2!"<<endl;ResumeThread(hSystem[3]);}Head_Run=-1;}void Wakeup(int pcbID, RESOURCE_ID ResID){ //将其插入就绪队列的末尾if(ResID==RES_IO1)Head_Block1=PCBTable[pcbID].NextProc;elseHead_Block2=PCBTable[pcbID].NextProc;AddtoQueue(&Head_Ready, pcbID);cout<<"进程:"<<PCBTable[pcbID].PID<<" "<<PCBTable[pcbID].Name<<"从进入就绪队列!"<<endl;}void DestroyProcess(int pcbID){ cout<<"进程:"<<PCBTable[pcbID].PID<<" "<<PCBTable[pcbID].Name<<"执行完毕!"<<endl;FreePCB(pcbID);ProcCount--; //进程总数减少Head_Run=-1;}void TimeOut(int pcbID){ //保存该进程的CPU现场PCBTable[pcbID].Reg1=Reg1;PCBTable[pcbID].Reg2=Reg2;PCBTable[pcbID].PC=PC;PCBTable[pcbID].Status=PS_READY;//插入到就绪队列中cout<<"进程:"<<PCBTable[pcbID].PID<<" "<<PCBTable[pcbID].Name<<"时间片用完,进入就绪队列1!"<<endl;AddtoQueue(&Head_Ready, pcbID);Head_Run=-1;}DWORD WINAPI Scheduler( LPVOID lpPara) //进程调度程序{ int nSel;while(1){ if(Head_Run==-1) //CPU空闲,选择一个合适的进程投入运行{ //此处选用FIFS算法if(Head_Ready!=-1){ nSel=Head_Ready;PCBTable[nSel].Status=PS_RUN;Head_Ready=PCBTable[Head_Ready].NextProc;Head_Run=nSel;cout<<"进程:"<<PCBTable[nSel].PID<<" "<<PCBTable[nSel].Name<<"被进程调度选中投入运行!"<<endl;ResumeThread(hSystem[1]); //唤醒CPU,继续工作}}if(ProcCount==0) //系统中所有用户进程运行完毕,退出{TerminateThread(hSystem[1],0); //停止CPUTerminateThread(hSystem[2],0); //停止IO1TerminateThread(hSystem[3],0); //停止IO2break;}}return 0;}DWORD WINAPI CPU_Thread(LPVOID lpPara ) //用来模拟CPU{ PCB *pcbRun;int nTime;while(1){ nTime=TIMESLICE;if (Head_Run!=-1){ PCB * pcbRun=&PCBTable[Head_Run];cout<<"进程:"<<pcbRun->PID<<" "<<pcbRun->Name<<"开始运行!"<<endl;Reg1=pcbRun->Reg1;Reg2=pcbRun->Reg2;PC=pcbRun->PC;if (Reg1!=RES_CPU && Reg1!=0){ cout<<"进程调度出现错误!"<<endl;ExitThread(0);}while( Reg1==RES_CPU ||Reg1==0 ) //开始运行{ if(Reg2<=0){ if(PC==-1){ DestroyProcess (pcbRun->PID); //进程执行完毕,将进程撤销break;}else{ Reg1=RESTable[PC].ResID;Reg2=RESTable[PC].Time;PC=RESTable[PC].Next;}}nTime--; //时间减少Reg2 --; //剩余时间减少if(nTime==0) //时间片用完{ TimeOut(pcbRun->PID );break;}}if(Reg1==RES_IO1||Reg1==RES_IO2)Block(pcbRun->PID,(RESOURCE_ID)Reg1);}SuspendThread(GetCurrentThread()); //无进程可运行,CPU休息}return 0;}DWORD WINAPI IO1_Thread(LPVOID AA ) //用来模拟IO1{ PCB *pcbBlock;int nTime;while(1){ while(Head_Block1!=-1){ pcbBlock=&PCBTable[Head_Block1];if(pcbBlock->Reg1!=RES_IO1){ cout<<"阻塞原语出现错误!"<<endl;ExitThread(0);}cout<<"进程:"<<pcbBlock->PID<<" "<<pcbBlock->Name<<"开始使用IO1!"<<endl;nTime=pcbBlock->Reg2;while(nTime--)Sleep(2); //进行IO操作cout<<"进程:"<<pcbBlock->PID<<" "<<pcbBlock->Name<<"使用IO1结束"<<endl;pcbBlock->Reg1=0;pcbBlock->Reg2=0;Wakeup(pcbBlock->PID, RES_IO1); //唤醒阻塞}SuspendThread(GetCurrentThread()); //无进程使用IO1设备,休息}return 0;}DWORD WINAPI IO2_Thread(LPVOID lpPara) //用来模拟IO2{PCB *pcbBlock;int nTime;while(1){ while(Head_Block2!=-1){ pcbBlock=&PCBTable[Head_Block2];if(pcbBlock->Reg1!=RES_IO2){ cout<<"阻塞原语出现错误!"<<endl;ExitThread(0);}cout<<"进程:"<<pcbBlock->PID<<" "<<pcbBlock->Name<<"开始使用IO2"<<endl;nTime=pcbBlock->Reg2;while(nTime--)Sleep(2); //进行IO操作cout<<"进程:"<<pcbBlock->PID<<" "<<pcbBlock->Name<<"使用IO2结束"<<endl;pcbBlock->Reg1=0;pcbBlock->Reg2=0;Wakeup(pcbBlock->PID, RES_IO2); //唤醒阻塞}SuspendThread(GetCurrentThread()); //无进程使用IO2设备,休息}return 0;}void Init(void){ int i;for(i=0;i<MAXPCBCOUNT;i++) //初始化PCB表,将表中的空闲空间构成静态链表PCBTable[i].NextProc=i+1;PCBTable[MAXPCBCOUNT-1].NextProc=-1;Head_Free=0;//指向空闲空间链表的第一个结点for(i=0;i<MAXRESCOUNT;i++)//初始化RES表,将表的空闲空间构成静态链表RESTable[i].Next=i+1;RESTable[MAXRESCOUNT-1].Next=-1;ResHead_Free=0;//指向空闲空间链表的第一个结点//就绪、运行、阻塞队列为空Head_Ready=-1;Head_Run=-1;Head_Block1=-1;Head_Block2=-1;ProcCount=0; //进程总数为0}//创建进程bool CreateProcess(){ int nPos, nResPos, nResPosPre;int nResID, nTime;nPos=NewPCB();if(nPos<0 ) //如果申请失败,则返回return false;PCBTable[nPos].PID=nPos; //设定进程ID为其在PCB表中的位置PCBTable[nPos].Status=PS_READY;cout<<"\n请输入进程名:";cin>>PCBTable[nPos].Name;cout<<"\n请输入进程的优先级:";cin>>PCBTable[nPos].Priority;nResPosPre=PCBTable[nPos].CodeAddr=-1;while(1){ cout<<"\n请输入该进程对资源的使用情况,当前系统中的资源及其编号如下:";cout<<"\n 1 ------------ CPU";cout<<"\n 2 ------------ IO1";cout<<"\n 3 ------------ IO2";cout<<"\n请输入资源号及使用时间,输入0退出,格式[资源号时间]:";cin>>nResID>>nTime;if ( nResID>=1 && nResID<=3 && nTime>0){ nResPos=NewRES();if(nResPos<0) //申请资源空间失败{ cout<<"\n申请资源空间失败!";break;}RESTable[nResPos].ResID=(RESOURCE_ID) nResID;RESTable[nResPos].Time=nTime;RESTable[nResPos].Next=-1;if(nResPosPre==-1)PCBTable[nPos].CodeAddr=nResPos;elseRESTable[nResPosPre].Next=nResPos;nResPosPre=nResPos;}else if(nResID==0)break;elsecout<<"\n输入的数据非法!!!";}PCBTable[nPos].Reg1=0;PCBTable[nPos].Reg2=0;PCBTable[nPos].PC=PCBTable[nPos].CodeAddr;AddtoQueue(&Head_Ready, nPos); //将该进程插入到就绪队列末尾中ProcCount++;return true;}void Start(void){ DWORD id;hSystem[0]=CreateThread(NULL, 0 , Scheduler,NULL ,THREAD_PRIORITY_ABOVE_NORMAL, &id);hSystem[1]=CreateThread(NULL, 0, CPU_Thread, &PCBTable[Head_Ready],THREAD_PRIORITY_NORMAL, &id);hSystem[2]=CreateThread(NULL, 0, IO1_Thread, &PCBTable[Head_Ready],THREAD_PRIORITY_NORMAL, &id);hSystem[3]=CreateThread(NULL, 0, IO2_Thread, &PCBTable[Head_Ready],THREAD_PRIORITY_NORMAL, &id);WaitForMultipleObjects(4, hSystem, TRUE, INFINITE);}void main(void){int nSel,i ;Init();while(1){ cout<<"\n************进程管理模拟程序主菜单*****************:";cout<<"\n 1 ------------ 创建进程";cout<<"\n 2 ------------ 进程浏览";cout<<"\n 3 ------------ 运行";cout<<"\n 0 ------------ 退出系统";cout<<"\n请输入你的选择[0-3]:";cin>>nSel;switch(nSel){case 1: CreateProcess(); break;case 2: break;case 3: Start(); break;case 0:for (i = 0; i < 4; i++)CloseHandle(hSystem[i]);exit(0);break;default:cout<<"\n输入了错误的选择!!!"<<endl; break;}}}五、实验任务1、熟悉进程管理与组织时所采用的数据结构,掌握进程控制时各原语的功能、掌握常见的进程调度算法。