首页 >excel操作 > 内容

短进程优先算法C语言实现

2023年10月29日 21:36
短进程优先算法C语言实现
目录:
1、实验说明:
2、程序定义:
3、源代码示例:
4、运行结果:
5、算法流程图:
6、C语言知识点:

1、实验说明:
答:本实验实现了短进程优先的进程调度操作,但因为是非抢占式,所以实现起来比较简单。

短进程优先算法是以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的运行时间来衡量的。在把短作业优先调度算法用于作业调度时,它将从外存的作业后备队列中选择若干个估计运行时间最短的作业,优先将它们调入内存运行。


2、程序定义:

(1)PCB:

①作业号 ②到达时间 ③需要运行时间 ④开始时间 ⑤完成时间 ⑥周转时间 ⑦带权周转时间

(2)公式:

完成时间 = 开始时间 + 需要运行时间

周转时间 = 完成时间 - 到达时间

带权周转时间 = 周转时间 / 需要运行时间

(3)附:当全部进程执行完毕,

①打印出平均带权周转时间

②打印出调度顺序

③打印出平均周转时间

最先到的进程从0时刻到达,首先开始执行它。

比较处于等待队列中的进程的需要运行时间, 谁的需要运行时间短就先执行谁,如果需要运行时间相同则看它们的到达时间,到达时间早的先执行。


3、源代码示例:
#include <stdio.h>#include <stdlib.h>#include <string.h>#define TAKEIN "Takein"//吸纳状态 #define WAIT "Wait"//就绪状态 #define RUN "Run"//运行状态 #define FINISH "Finish"//完成状态 #define JOBNUMBER 5 //设置进程测试数为5 #define MIN 100  typedef struct PCB{char jobName[10];//作业号 int arriveTime;//到达时间 int runTime;//需要运行时间 int startTime;//开始时间 int endTime;//完成时间 int turnoverTime;//周转时间 float useWeightTurnoverTime;//带权周转时间char processStatus[10];//进程状态 };static int currentTime = 0; static int finishNumber = 0;char JobArray[JOBNUMBER][10];static int indexJob = 1;//创建PCBvoid createPCB(struct PCB* pcb){ freopen("input.txt","r",stdin); printf("从文件中读入三个参数的数据:\n"); printf("作业号 到达时间 需要运行时间\n");  for(int i = 0; i < 5; i++){ scanf("%s", &pcb[i].jobName);//作业号  scanf("%d", &pcb[i].arriveTime);//到达时间  scanf("%d", &pcb[i].runTime);//需要运行时间  pcb[i].startTime = 0; pcb[i].endTime = 0; pcb[i].turnoverTime = 0; pcb[i].useWeightTurnoverTime = 0.0; strcpy(pcb[i].processStatus, TAKEIN); printf("%s\t%d\t%d\n",pcb[i].jobName, pcb[i].arriveTime,pcb[i].runTime);}printf("---------------------------------------------\n"); } //打印用途void printJob(struct PCB* pcb){printf("当前时间为%d\n", currentTime);printf("作业号 到达时间 需要运行时间 开始时间 完成时间 周转时间 带权周转时间 进程状态\n");for(int i = 0; i < JOBNUMBER; i++){if(strcmp(pcb[i].processStatus, FINISH) == 0)//如果进程为finish状态,这样输出 printf("%s\t%d\t%4d\t\t%d\t%d\t  %d\t%.2f\t%s\n", pcb[i].jobName, pcb[i].arriveTime, pcb[i].runTime, pcb[i].startTime, pcb[i].endTime, pcb[i].turnoverTime, pcb[i].useWeightTurnoverTime, pcb[i].processStatus);else if(strcmp(pcb[i].processStatus, RUN) == 0)//如果进程为run状态,这样输出 printf("%s\t%d\t%4d\t\t%d\t运行中\t  none\tnone  \t%s\n", pcb[i].jobName, pcb[i].arriveTime, pcb[i].runTime, pcb[i].startTime, pcb[i].processStatus);else //如果进程为take in或wait状态,这样输出printf("%s\t%d\t%4d\t\t未运行\tnone\t  none\tnone  \t%s\n", pcb[i].jobName, pcb[i].arriveTime, pcb[i].runTime, pcb[i].processStatus);}printf("---------------------------------------------\n");} //根据当前时间修改status状态void statusConfirm(struct PCB* pcb){for(int i = 0; i < JOBNUMBER; i++){//将当前时间为进程的到达时间,修改take in状态改为Wait状态 if(currentTime >= pcb[i].arriveTime && strcmp(pcb[i].processStatus, TAKEIN) == 0){strcpy(pcb[i].processStatus, WAIT); }}} //确定当前时间wait进程中最短进程的数组下标,没有wait进程则返回-1 int shortIndex(struct PCB* pcb){int min = MIN, temp = -1;statusConfirm(pcb);for(int i = 0; i < JOBNUMBER; i++){if(strcmp(pcb[i].processStatus, WAIT) == 0){if(pcb[i].runTime <= min){min = pcb[i].runTime;temp = i;} }}return temp;}  //运行第一个到达的进程void runFirstJob(struct PCB* pcb){pcb[0].startTime = currentTime;int endTime = pcb[0].startTime + pcb[0].runTime;strcpy(pcb[0].processStatus, RUN);while(true){if(currentTime == endTime){pcb[0].endTime = endTime; pcb[0].turnoverTime = pcb[0].endTime - pcb[0].arriveTime;pcb[0].useWeightTurnoverTime = pcb[0].turnoverTime * 1.0 / pcb[0].runTime;strcpy(pcb[0].processStatus, FINISH);finishNumber++;break;}else{statusConfirm(pcb);printJob(pcb);currentTime++;}}} //运行其他进程 void runOtherJob(struct PCB* pcb){int index = shortIndex(pcb);strcpy(JobArray[indexJob++], pcb[index].jobName);if(index == -1)//没有进程处于wait状态 printJob(pcb); else{pcb[index].startTime = currentTime;pcb[index].endTime = pcb[index].startTime + pcb[index].runTime;pcb[index].turnoverTime = pcb[index].endTime - pcb[index].arriveTime;pcb[index].useWeightTurnoverTime = pcb[index].turnoverTime * 1.0 / pcb[index].runTime;strcpy(pcb[index].processStatus, RUN);while(true){statusConfirm(pcb);if(currentTime == pcb[index].endTime){strcpy(pcb[index].processStatus, FINISH);finishNumber++;if(finishNumber == JOBNUMBER){printJob(pcb);}break;}else{printJob(pcb);currentTime++;}}} }  //比较各个进程之间的到达时间,按升序排列 void compare(struct PCB* pcb){for(int i = 0; i < JOBNUMBER; i++){int min = pcb[i].arriveTime;int minIndex = i;for(int j = i + 1; j < JOBNUMBER; j++){if(pcb[j].arriveTime < min){min = pcb[j].arriveTime;minIndex = j;}}struct PCB temp = pcb[i];pcb[i] = pcb[minIndex];pcb[minIndex] = temp;}}//计算平均带权周转时间 float weightTurnoverTimeCount(struct PCB* pcb){float sum = 0.0;for(int i = 0; i < JOBNUMBER; i++){sum += pcb[i].useWeightTurnoverTime;}return sum / JOBNUMBER;}//计算平均周转时间 float turnOverTimeCount(struct PCB* pcb){float sum = 0.0;for(int i = 0; i < JOBNUMBER; i++){sum += pcb[i].turnoverTime;}return sum / JOBNUMBER;} //开始进程调度 void start(struct PCB* pcb){compare(pcb);int firstArriveTime = pcb[0].arriveTime; //进程调度位currentTime每次加1,直到进程全部被调度完成为止 for(; finishNumber != 5; currentTime++){if(currentTime < firstArriveTime)//当前时间小于第一个节点到来时间时,直接打印 printJob(pcb);else if(currentTime == firstArriveTime)//当时间来到第一个进程的到达时间,调度该进程 runFirstJob(pcb);else{ //根据短进程优先开始调度currentTime--; runOtherJob(pcb);}  }printf("1、进程调度顺序为:%s, %s, %s, %s, %s\n", pcb[0].jobName, JobArray[1], JobArray[2], JobArray[3], JobArray[4]);printf("2、平均周转时间为:%.2f\n",turnOverTimeCount(pcb));printf("3、平均带权周转时间为:%.2f\n", weightTurnoverTimeCount(pcb));printf("------------------测试完毕 版权归邓钦艺所有---------\n");}//主函数 int main(){struct PCB pcb[JOBNUMBER];createPCB(pcb);start(pcb);return 0;}


4、运行结果:
(1)外部input.txt文件
图4.1 外部文件

(2)结果截图:

①当前时间为0时,五个进程全部进入到后备队列中,为take in状态;

当前时间为1时,job5开始执行,进程状态由take in转换为run;

当前时间为2时,job3到达,进程状态由take in转换为run;

当前时间为3时,job1到达,进程状态由take in转换为run,job5运行结束,进程状态由run转换为finish,job3开始执行,进程状态由wait转换为run;

图4.2 结果截图1

当前时间为5时,job3运行结束,进程状态由run转换为finish,job1到达时间为5,因此无需等待,直接运行,进程状态由take in直接转换为run;

当前时间为6时,job4到达,进程状态由take in转换为wait;

当前时间为8时,job2运行结束,进程状态由run转换为finish,job1开始执行,进程状态由wait转换为run;

图4.3 结果截图2

当前时间为12时,job1运行结束,进程状态由run转换为finish,job4开始执行,进程状态由wait转换为run;

图4.4 结果截图3

当前时间为17时,job4运行结束,进程状态由run转换为finish,五个进程状态均为finish,进程调度完毕,退出调度算法,打印出进程调度顺序,平均周转时间,以及平均带权周转时间。

图4.5 结果截图4



5、算法流程图:

图5.1 算法流程图

6、C语言知识点:

答:把大一的课件找到,将要用到的C语言基本知识复习了一下,做了些笔记。

①二级指针:指向指针的指针,指针变量中存放一级指针变量的地址。

②int **ptr:表示指向“一群”指向整数的指针的指针。

int *p[5]:表示指向5个指向整数的指针的指针。

int **ptr因为是指针的指针,需要两次内存分配才能使用其最终内容。

指针数组名p是二级指针常量,指针数组作形参,int **ptr与int *p[5]完全等价。

③内存动态分配:

A)非静态的局部变量是分配在内存中的动态存储区中的,这个存储区是称为栈的区域。

B)内存动态分配区域,用来存放一些临时用的数据,这些数据需要时随时开辟,不需要时随时释放,存放在堆区。

C)对内存的动态分配是通过系统提供的库函数来实现的,主要有malloc,calloc,free和realloc这四个函数。

④A)malloc函数(memory allocate):

void *malloc(unsigned int size):在内存的动态存储区中分配一个长度为size的连续空间,返回的指针指向该分配域的开头位置。

B)calloc函数:

void *calloc(unsigned n, unsigned size):在内存的动态存储区中分配n个长度为size的连续空间,函数返回指向所分配域的起始位置的指针;如果分配不成功,返回null。

C)free函数:

void *free(void * p):释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。p应是最近一次调用calloc或malloc函数时得到的函数返回值。

D)realloc函数:

void *realloc(void * p, unsigned int size):如果已经通过malloc函数或calloc函数获得了动态空间,想改变其大小,可以用recalloc函数重新分配。用realloc函数将p所指向的动态空间的大小改变为size。p的值不变。如果重分配不成功,返回NULL。

⑤结构体变量不能整体引用,只能引用变量成员。

引用方式:

a)结构体变量名.成员名

b)指针变量->成员名

ptr->num在计算机内部会被转化为(*ptr).num

虽然最后为了代码好写由指针全部推掉转换为了结构体数组,但复习过后,下次人工智能以及操作系统的实验都会用到。



参考文章:https://blog.csdn.net/Remoa_Dengqinyi/article/details/52864840

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时候联系我们修改或删除,在此表示感谢。

特别提醒:

1、请用户自行保存原始数据,为确保安全网站使用完即被永久销毁,如何人将无法再次获取。

2、如果上次文件较大或者涉及到复杂运算的数据,可能需要一定的时间,请耐心等待一会。

3、请按照用户协议文明上网,如果发现用户存在恶意行为,包括但不限于发布不合适言论妄图

     获取用户隐私信息等行为,网站将根据掌握的情况对用户进行限制部分行为、永久封号等处罚。

4、如果文件下载失败可能是弹出窗口被浏览器拦截,点击允许弹出即可,一般在网址栏位置设置

5、欢迎将网站推荐给其他人,网站持续更新更多功能敬请期待,收藏网站高效办公不迷路。

      



登录后回复

共有0条评论