目 录
在Linux/UNIX/Windows下编制一个程序,模拟实现一个简单的进程管理子系统,它由进程建立模块、进程撤消模块、进程控制表组成,(此外还可能包括选作的进程切换和调度模块)。
在1题的基础上,进一步可选做模拟实现进程切换。希望能实现时间片满或接到sleep调用(或信号时)进行进程切换(选择其一即可)。
若要实现时间片,假设时间片为1秒钟,设定底层环境OS每个1秒向该系统发一个信号,本子系统将本子系统的进程切换和调度模块设定为该信号的处理程序。或者每当接到子进程发出的的sleep调用(或信号)时进行进程切换,这里子进程发出的sleep调用(或信号)代表实际系统中可能发生的sleep( )调用、等待某一时间发生等情况,进程调度采用简单的FIFO算法。
(本题作为一道思考选作实验题:由于是在实际OS中模拟实现,故子系统无法完全控制其建立的所有子进程的进程状态变化,象当前进程这样的概念都不太好模拟,需要设法解决或假设。
具体实现时参考1题~3题要求)
2数据结构设计
2.1PCB定义
typedef struct PCB
{ //定义进程控制快PCB
float ID; //进程标识符
int Priority; //优先数
int Alltime; //进程还需要运行的时间
int CPUtime; //已用CPU时间
int State; //状态
float father; //父进程
float child; //子进程
int Max[m]; //最大需求
int Allocation[m];//已分配
int Need[m]; //需求
PCB* next; //队列指针
}pcb;
2.2队列定义
class Queue
{
public:
Queue():rear(NULL),first(NULL){}; //构造函数并初始化 ~Queue();//析构函数
void enqueue(pcb *p);//入队函数
void dequeue(pcb *p);//出队函数
void del(float id);
void dispaly(); //显示函数
int find(float id);
void search1(float id,int x);
float search2(float id,int x);
bool isempty(){return first==NULL&&rear==NULL;}//判队列空否
private:
pcb *first,*rear; //队首、队尾指针
};
2.3全局变量定义
queue execute,ready,block; //定义就绪阻塞执行队列
int num=0; //进程数
int Available[3]; //定义资源
2.4主函数模块
main()
{
for(int i=0;i<3;i++)
Available[i]=30;
cout<<"\t\t资源初始化完毕!"<<endl;
menu();
}
2.5函数定义
float a[8]={-1,-1,-1,-1,-1,-1,-1,-1};
void output();//输出函数
void clean();//清屏
void menu();//菜单函数
void create();//创建函数
void createchild(pcb *p);//创建子进程函数
void run();//执行函数
void lock();//阻塞函数
void change();//唤醒函数
void jixu();//选择是否继续运行或退出程序
3算法设计
3.1算法流程图
3.2设计思想
主函数是实现进程管理的入口,在入口处需输入进程名称,然后输入进程的状态选项,完成后,则通过相应的调度算法进行进程机的调度,同时也将结果显示在屏幕上。本次实验通过模拟多个进程的同步运行,实现了进程就绪、运行、阻塞三个状态的转换,并可以根据用户要求改变进程的状态,实现进程切换。
3.3算法描述
创建进程——根据进程的顺序依次放入就绪队列,并创建其子进程副本;
void create()
{
创建进程
将进程送入就绪队列
创建其子进程
将子进程送入就绪队列
是否继续
}
执行进程——管理系统将就绪队列中的第一个进程调入运行队列;
void run()
{
判断未使用资源能否满足进程
否,将进程从就绪队列取出,送入阻塞队列
是,将进程从就绪队列取出,送入执行队列
若进程执行完毕,则自动撤销进程
是否继续
}
阻塞进程——将执行队列中进程调入阻塞队列;
void block()
{
判断执行队列是否有进程执行
若有,则将进程从执行队列取出送入阻塞队列
是否继续
}
唤醒进程——管理系统将阻塞队列中的第一个进程调入就绪队列;
void change()
{
判断阻塞队列是否有进程执行
是,将进程从阻塞队列取出,送入就绪队列
是否继续
}
结束进程——管理系统撤销所选进程,并释放其所占用的资源;
void revoke()
{
从就绪、执行、阻塞队列中找到该进程
释放其所占资源
修改其父子进程信息
撤销进程
是否继续
}
4测试数据及程序运行情况
4.1菜单运行界面
如上图所示:进入进程管理菜单,用户可进行选择(1-6)。
用户输入d,会提示输入有误,并再次进入界面让用户进行第二次选择(如下图所示)
4.2进程创建界面
如上图所示:创建了3个进程,进程ID号为手动输入,优先数、运行时间、所需资源数目、已分配资源数目为随机生成数,并依次创建其子进程。选择(1-2),继续或者结束退出程序。
如果用户创建ID重复的进程,会自动再次进入创建窗口进行创建新的进程。
如上图所示,创建两个进程ID为3的进程,会自动再次进入创建窗口进行创建新的进程。
4.3进程运行界面
如上图所示:根据先来先服务算法,先对进程1进行服务。其他进程在就绪队列等待。选择(1-2),继续或者结束退出程序。
如上图所示:有进程在执行时,如果用户选择进程执行,会显示“已有进程在执行!操作失败”。如此,用户可选择(1-2),继续或者结束退出程序。
4.4进程阻塞界面
图1
图2
图3
如图1所示:创建一个大于Allocation的资源数目,导致如图2所示的进程阻塞,由于资源数不够,所以如图3所示将其加入阻塞队列,不能进一步运行。
4.5进程唤醒界面
4.6进程撤销界面
5实验中出现的问题及解决方法
5.1出现问题
在菜单用户选择功能时,若用户错误输入了非菜单选择(1-6)的字符,系统直接结束运行。
5.2解决办法
在用户输入选择后加入了判断,如果菜单功能以外的数字,则反馈给用户"输入有误,请重新输入!";输入不是所定义的类型(int),则清空输入流缓冲,让用户继续输入。
while(n<=0||n>6)
{
cout<<"\t\t\t\t!!!输入有误,请重新输入!!!"<<endl<<endl;
menu();
if(!(cin>>n))
{
cin.clear();
}
cin>>n;
}