操作系统实验三(进程调度之优先数与时间片)
一. 实验目的
理解进程运行的并发性
理解进程各种状态及其之间的转换
理解进程管理中PCB的结构
掌握优先数进程调度算法
二. 实验内容
用 VC编写实现进程调度算法模拟进程调度的实现过程。调度算法采用的是动态优先数与时间片相结合的算法。要求如下:
- 进程相关信息如进程标识符及进程所需时间都放入PCB中;
- 设计运行、完成和就绪三个进程队列;
- 就绪队列按优先数从小到大排列,每次选择优先数最大的就绪进程运行。初始优先数定为用一个较大的数(如30)减去进程运行时间,随着进程的运行对优先数进行调整;
- 进程每执行一次,优先数减一个固定值(如3),CPU时间加1,进程所需时间减1.如果进程所需时间变为0,说明进程运行完毕,将其状态置为"F",将其PCB插入到完成队列中,此时若就绪队列不空,则将就绪队列的第一个PCB变为运行状态。 如果进程未完成,则将其优先数和就绪队列中第一个PCB优先数比较,如果小,则将其变为就绪态,插入就绪队列中适当位置,同时将就绪队列中第一个PCB变为运行态。重复上述过程直到就绪队列为空,所有进程成为完成状态。
相关数据结构:
typedef struct node{
char name[10]; //进程标识符
int prio; //进程优先级
int cput; //进程占用的CPU时间
int needt; //进程离完成还需要的CPU时间
char state; //进程状态 struct node *next;
}PCB;
三、实验代码
参考实验二中的代码自行完成该算法代码。
要求:
编写算法实现的流程图
编程实现题目要求的功能
测试多组数据的实验结果
#include <iostream> #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <bits/stdc++.h> using namespace std; //定义动态申请空间的函数 #define getpch(type) (type*)malloc(sizeof(type)) typedef struct node { int ID;//进程的标识符 int prio;//进程的优先级 int cput;//进程占用的CPU时间 int ncput;//进程离完成还需要的CPU时间 char state;//进程的状态 R运行,W等待,在run中使用F-T。 struct node *next; }PCB; PCB *ready, *run, *finish;//准备,运行,完成。 void InitProcess();//进程的初始化设置 void insertByDesc(PCB *p);//插入节点,按照从大到小排序(优先级高的先运行) void printreadyinfo();//输出就绪队列的信息 void processrunning();//进程开始运行 void JoinCPU();//从进程中选取一个进程进入CPU开始运行 void showrun(PCB *p);//显示正在运行的进程(显示过程) void showfinish(PCB *p);//显示完成的信息 void setfinish(PCB *p);////进程完成,设置为完成 //主函数 int main() { run = getpch(PCB);//申请节点空间 finish =getpch(PCB); ready = getpch(PCB); ready->next = NULL; run->next = NULL; finish->next = NULL; InitProcess();//初始化进程 processrunning(); return 0; } void showrun(PCB *p) { printf("进程运行的信息:\n"); cout<<"ID"<<" "<<"Prio"<<" "<<"cput"<<" "<<"ncput"<<" "<<"state"<<endl; printf("%-4d %-7d %-7d %-7d %-7c\n", p->ID, p->prio, p->cput, p->ncput, p->state); } void showfinish(PCB *p) { printf("完成的进程信息:\n"); cout<<"ID"<<" "<<"Prio"<<" "<<"cput"<<" "<<"ncput"<<" "<<"state"<<endl; printf("%-4d %-7d %-7d %-7d %-7c\n", p->ID, p->prio, p->cput, p->ncput, p->state); } //进程完成,设置为完成 void setfinish(PCB *p) { PCB *r; if (p->ncput == 0) {//如果运行所需时间为0,放入finish r = finish; while (r->next != NULL) { r = r->next; } p->state = 'F';//将当前进程置为完成状态 p->next = r->next; r->next = p; showfinish(p);//输出完成的信息 } } //从进程中选取一个进程进入CPU开始运行 void JoinCPU() { if (ready->next != NULL) {//如果就绪队列不为空,第一个PCB置运行 run->next = ready->next;//开始运行 ready->next = ready->next->next;//第一个从就绪队列删除 run->next->state = 'R';//运行的进程状态改为R run->next->prio -= 3;//每进入CPU一次优先级-3 run->next->cput += 1;//CPU占用的时间+1 run->next->ncput -= 1;//一共还需要的时间-1 } } void processrunning() { JoinCPU(); setfinish(run->next);//时间为零置finish if (run->next->state != 'F') showrun(run->next); while (1) { if (ready->next != NULL && run->next->prio < ready->next->prio) { //小于第一个PCB优先数就将其插入就绪并调用下一个进程 if (run->next->state != 'F')//如果进程已完成就不用插入就绪 insertByDesc(run->next);//重新进行排序 JoinCPU(); setfinish(run->next); if (run->next->state != 'F') showrun(run->next); } else { run->next->prio -= 3; run->next->cput += 1; run->next->ncput -= 1; setfinish(run->next); if (run->next->state != 'F') showrun(run->next); if (ready->next == NULL) { break; } } } } //输出就绪队列的信息 void printreadyinfo() { PCB *p; p = ready->next; cout<<"就绪进程的信息(ready info)"<<endl; cout<<"ID"<<" "<<"Prio"<<" "<<"cput"<<" "<<"ncput"<<" "<<"state"<<endl; while (p != NULL) { printf("%-4d %-7d %-7d %-7d %-7c\n", p->ID, p->prio, p->cput, p->ncput, p->state); p = p->next; } } //插入节点,按照从大到小排序(优先级高的先运行) void insertByDesc(PCB *p){ PCB *tmp; tmp = ready; while (tmp->next != NULL && tmp->next->prio >= p->prio) {//从大到小排序 tmp = tmp->next; } //第一个节点 p->next = tmp->next; tmp->next = p; } //进程状态的初始化: void InitProcess() { PCB *p; int n; printf("情输入进程的个数:"); cin>>n;//输入了进程的个数; cout<<"请输入进程的标识符和程占用的CPU时间"<<endl; for (int i = 1; i <= n; i++) { p = getpch(PCB); int id, pri, needt;//设置变量,进程的标识,优先级,占用CPU的时间。 cin>>id>>needt; p->ID = id; p->prio = 30;//优先级初始状态为30 p->cput = 0;//初始化时还未占用CPU p->ncput = needt;//一共需要的CPU时间 p->state = 'w';//状态等待。 insertByDesc(p); } printreadyinfo(); }
一纸高中万里风,寒窗读破华堂空。
莫道长安花看尽,由来枝叶几相同?