在遭受了大概前后三个下午的折磨之后,我决定把这个痛苦的经历的结果记录下来,于是有了我的第一篇CSDN的博客。
优先级调度和轮转调度的c语言实现
先简述一下实现的过程吧
就是用结构体代表一个个的进程,然后通过链表来实现调度过程中的排序
其实优先级调度就是从那么多个进程里面选出一个优先级最高的进程放入CPU中运行,运行完一个时间片后更改此进程相应的变量,再把优先级减8,最后判断此进程是否完成,然后把此进程放到相应队列的队尾。
轮转调度和优先级调度十分相似,只是它的结构体中的变量和优先级调度不一样,然后把选择最高优先级改成选择就绪队列中的第一个进程就可以了。
所以其实拿到其中的一个代码就再稍微改一下就可以得到两种不同的调度方法了,所以不要像我一开始还打算写两个完全不一样的……
好了话不多说,直接进入代码解析好了
优先级调度的重点代码解析
- 先新建一些可以用的指针
struct PCB *Move=head->next;
struct PCB *Max_Pri=head->next;
struct PCB *Tail; //尾指针
struct PCB *hT;
- 然后利用指针遍历选出就绪队列中优先级最高的进程
while(Move!=NULL){
if(Max_Pri->priority_number < Move->priority_number){
Max_Pri = Move;
}
Move = Move->next;
}
- 改变选中进程的某些属性(已运行时间+1,优先级-8,再判断此进程是否完成,如果完成把状态改为0,如果未完成则把状态改为1)
Max_Pri->used_time += Time_film;
Max_Pri->priority_number -= 8;
if(Max_Pri->used_time == Max_Pri->need_time){
Max_Pri->process_state = 0;
count++;
}
else{
Max_Pri->process_state = 1;
}
printf("进程 %d 被调度: \n",Max_Pri->process_name);
- 调用print函数(自定义的)输出此时的就绪队列和已完成队列
printf(" 就绪队列:\n");
print(head); //输出就绪队列
printf(" 已完成队列:\n");
print(h); //输出已完成队列
printf("\n");
- 把之前选中的优先级最高的进程从就绪队列里面取出来
Move = Max_Pri->cre;
Move->next = Max_Pri->next;
if(Move->next != NULL){
Move = Max_Pri->next;
Move->cre = Max_Pri->cre;
}
- 取出来后再判断一下进程是否已完成,如果已完成则放入已完成队列的队尾并把状态改成0(已完成),如果没有完成则放入就绪队列的队尾并把状态改回-1(就绪)
if(Max_Pri->process_state !=0){
printf("进程 %d 未完成,进入就绪队列 \n\n",Max_Pri->process_name);
Move = head;
while( Move->next!=NULL ){ //当被调出进程未完成时将其插入就绪队列尾部
Move = Move->next;
}
Tail = Move;
Max_Pri->cre = Tail;
Max_Pri->next = NULL;
Tail->next = Max_Pri;
}else{
printf("进程 %d 已完成,进入已完成队列 \n\n",Max_Pri->process_name);
Move =h;
while(Move->next!=NULL){
Move = Move->next;
}
hT = Move;
Max_Pri->cre = hT;
Max_Pri->next = NULL;
hT->next = Max_Pri;
}
if(Max_Pri->process_state !=0){
Max_Pri->process_state = -1;
}else{
Max_Pri->process_state = 0;
}
- 判断是否所有的进程都已经执行完毕,如果没有,则跳过if此段代码,重新调用此函数,进入循环
if(count == N){ //所有进程执行完毕
printf(" 就绪队列:\n");
print(head); //输出就绪队列
printf(" 已完成队列:\n");
print(h); //输出已完成队列
printf("\n");
printf(" 所有进程执行完毕!");
return;
}
//****************************循环调用
Process_scheduling(head,h);//此函数的函数名
}
其余的代码就基本上看一遍就能懂的了,所以就不解析了,试着自己分析分析吧。
关于轮转调度的也是,只是在前两个步骤有一点小小的变动,看一看就能明白,所以就直接贴代码了
优先级调度完整代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define Time_film 1 //时间片
int count = 0; //统计进程完成个数
int N;//进程个数
void print(struct PCB *head);
struct PCB{
int process_name; //进程名
int priority_number; //优先数,随机产生
int arrive_time; //到达时间,为进程的创建时间
int need_time; //需要运行的时间
int used_time; //已用CPU的时间,初始值为0
int process_state; //进程状态,1表示运行,0表示完成,-1表示就绪,初始值为-1
struct PCB *cre; //前驱指针域
struct PCB *next; //后驱指针域
};
void Process_scheduling(struct PCB *head,struct PCB *h){
//****************************
struct PCB *Move=head->next;
struct PCB *Max_Pri=head->next;
struct PCB *Tail; //尾指针
struct PCB *hT;
//****************************//寻找最高优先级进程
while(Move!=NULL){
if(Max_Pri->priority_number < Move->priority_number){
Max_Pri = Move;
}
Move = Move->next;
}
//****************************改变选中进程的属性
Max_Pri->used_time += Time_film;
Max_Pri->priority_number -= 8;
if(Max_Pri->used_time == Max_Pri->need_time){
Max_Pri->process_state = 0;
count++;
}
else{
Max_Pri->process_state = 1;
}
printf("进程 %d 被调度: \n",Max_Pri->process_name);
//*****************************输出此时的两个队列
printf(" 就绪队列:\n");
print(head); //输出就绪队列
printf(" 已完成队列:\n");
print(h); //输出已完成队列
printf("\n");
//****************************//将最高优先级进程提出来
Move = Max_Pri->cre;
Move->next = Max_Pri->next;
if(Move->next != NULL){
Move = Max_Pri->next;
Move->cre = Max_Pri->cre;
}
//*****************************把拿出来的相应的进程放入队列
if(Max_Pri->process_state !=0){
printf("进程 %d 未完成,进入就绪队列 \n\n",Max_Pri->process_name);
Move = head;
while( Move->next!=NULL ){ //当被调出进程未完成时将其插入就绪队列尾部
Move = Move->next;
}
Tail = Move;
Max_Pri->cre = Tail;
Max_Pri->next = NULL;
Tail->next = Max_Pri;
}else{
printf("进程 %d 已完成,进入已完成队列 \n\n",Max_Pri->process_name);
Move =h;
while(Move->next!=NULL){
Move = Move->next;
}
hT = Move;
Max_Pri->cre = hT;
Max_Pri->next = NULL;
hT->next = Max_Pri;
}
//********************************再把状态改回去
if(Max_Pri->process_state !=0){
Max_Pri->process_state = -1;
}else{
Max_Pri->process_state = 0;
}
if(count == N){ //所有进程执行完毕
printf(" 就绪队列:\n");
print(head); //输出就绪队列
printf(" 已完成队列:\n");
print(h); //输出已完成队列
printf("\n");
printf(" 所有进程执行完毕!");
return;
}
//****************************循环调用
Process_scheduling(head,h);
}
void print(struct PCB *head){ //输出队列函数
if(head->next == NULL){
printf("队列为空\n");
return;
}
printf("进程号 已占用cpu时间 所需时间 优先级 状态\n");
struct PCB *fry = head->next;
while(fry != NULL){
printf(" %d ",fry->process_name);
printf("%d ",fry->used_time);
printf("%d ",fry->need_time-fry->used_time);
printf("%d ",fry->priority_number);
if(fry->process_state == -1){
printf("%s","W");
}else if(fry->process_state == 1){
printf("%s","R");
}else{
printf("%s","F");
}
printf("\n");
fry = fry->next;
}
printf("\n");
}
int main(){
printf("---------优先级调度---------\n");
printf("输入进程数:\n");
scanf("%d",&N);
struct PCB *head; //头指针
struct PCB Pro[N+1]; //创建 N+1 个进程
struct PCB *h;
struct PCB q[N+1];
h = &q[0];
head = &Pro[0];
printf("请输入%d个进程号以及运行时间:\n",N);
for(int j=1;j<=N;j++){
scanf("%d %d",&Pro[j].process_name,&Pro[j].need_time);
}
//****************************
//设置进程参数
Pro[0].process_name = 0;
Pro[0].cre = NULL;
Pro[0].next = &Pro[1];
Pro[0].priority_number = 0;
int i=0;
for(i=1;i<=N;i++){
Pro[i].priority_number = 100-Pro[i].need_time;
Pro[i].arrive_time = 0;
Pro[i].used_time = 0;
Pro[i].process_state = -1;
}
for(i=1;i<=N;i++){ //形成双向队列
if( i == N ){
Pro[i].cre = &Pro[i-1];
Pro[i].next = NULL;
break;
}
Pro[i].cre = &Pro[i-1];
Pro[i].next = &Pro[i+1];
}
//****************************
printf(" 进程初始状态: \n");
print(head); //输出初始队列状态
Process_scheduling(head,h); //调用进程调度函数(最高优先级)
return 0;
}
轮转调度完整代码
#include<iostream>
#include<string>
#include <string.h>
int currentTime = 0;//当前时间
int number = 0;
//using namespace std;
struct pcb {
int pName;//进程名
struct pcb *next;//指向下一个进程
struct pcb *cre;//指向上一个进程
int arriveTime;//到达时间
int serviceTime;//总共需要运行的时间
int estimatedRunningtime;//还需要的运行时间
int usedtime;//++
int state;//进程的状态
int filmtime;//时间片的长度
int flag; //计算运行了多少次
};
void printing(struct pcb *p){
if(p->next == NULL){
printf("队列为空\n");
return;
}
printf("进程号 已占用CPU时间 所需时间 计数 时间片长度 状态\n");
struct pcb *fry = new struct pcb;
fry = p->next;
while(fry != NULL){
printf(" %d ",fry->pName);
printf("%d ",fry->usedtime);
printf("%d ",fry->estimatedRunningtime);
printf("%d ",fry->flag );
printf("%d ",fry->filmtime );
if(fry->state == -1){
printf("%s","W");
}else if(fry->state == 1){
printf("%s","R");
}else{
printf("%s","F");
}
printf("\n");
fry = fry->next;
}
}
void runProcess(struct pcb *p, struct pcb *h,int n) {//运行进程
//*******************************************每次都是取队头
struct pcb *q = p;
struct pcb *m = p->next;
struct pcb *Tail; //未完成的进程的尾指针
struct pcb *hT;//完成的进程的尾指针++
//********************************************改变选中进程的属性
m->estimatedRunningtime-=m->filmtime;
m->usedtime+=m->filmtime;
m->flag+=1;
currentTime+=m->filmtime;
if(m->usedtime>=m->serviceTime){
m->state = 0;
m->estimatedRunningtime = 0;
m->usedtime = m->serviceTime;
number++;
} else{
m->state = 1;
}
printf("进程 %d 被调度: \n",m->pName);
//************************************输出此时的两个队列
printf(" 就绪队列:\n");
printing(p);
printf(" 已完成队列:\n");
printing(h);
printf("\n\n");
//*******************************************把进程拿出来
q = m->cre;
q->next = m->next;
if(q->next != NULL){
q = m->next;
q->cre =m->cre;
}
//********************************************把拿出来的相应的进程放入队列
if(m->state != 0){
printf("进程 %d 未完成,进入就绪队列 \n\n",m->pName );
q = p;
while( q->next!=NULL ){
q = q->next;
}
Tail = q;
m->cre = Tail;
m->next = NULL;
Tail->next = m;
}else{
printf("进程 %d 已完成,进入已完成队列 \n",m->pName );
q = h;
while(q->next!=NULL){
q = q->next;
}
hT = q;
m->cre = hT;
m->next = NULL;
hT->next = m;
}
//************************************再把状态改回去
if(m->state !=0){
m->state = -1;
}else{
m->state = 0;
}
if(number == n){ //所有进程执行完毕 ++
printf(" 就绪队列:\n");
printing(p); //输出就绪队列
printf(" 已完成队列:\n");
printing(h); //输出已完成队列
printf("\n");
printf("------所有进程执行完毕!------\n");
return;
}
runProcess(p,h,n);
}
int main() {
printf("---------轮转调度---------\n");
struct pcb *p;
struct pcb *h;
int n;
printf("输入进程数:\n");
scanf("%d",&n);
struct pcb q[n+1];
h = &q[0];
q[0].pName = 0;
q[0].cre = NULL;
struct pcb Pro[n+1]; //创建 N+1 个进程-----就绪状态队列
p = &Pro[0];
printf("请输入%d个进程号以及运行时间:\n",n);
for(int j=1;j<=n;j++){
scanf("%d %d",&Pro[j].pName,&Pro[j].serviceTime);
}
for(int i=0;i<=n;i++){
if(i==0){
Pro[i].pName = 0;
Pro[i].cre = NULL;
Pro[i].next = &Pro[i+1];
continue;
}
Pro[i].arriveTime=0;
Pro[i].filmtime=2;
Pro[i].estimatedRunningtime=Pro[i].serviceTime;
Pro[i].state = -1;
Pro[i].usedtime = 0;
Pro[i].flag = 0;
}
for(int i=1;i<=n;i++){ //形成双向队列
if( i == n ){
Pro[i].cre = &Pro[i-1];
Pro[i].next = NULL;
break;
}
Pro[i].cre = &Pro[i-1];
Pro[i].next = &Pro[i+1];
}
printf(" 进程初始状态: \n");
printing(p); //输出初始队列状态
printf("\n");
runProcess(p,h,n);
return 0;
}
最后得说明一下我的代码是根据一个博主的代码再经过自己的修改得到的,在这里贴一下源代码的出处:https://www.cnblogs.com/chiweiming/p/9028002.html
如果有写的不清楚或者写的不对的地方的欢迎留言交流噢