目录
一、实验目的
1、掌握进程的存在形式
2、掌握先来先服务、短进程优先调度算法
3、掌握调度方案的评价指标
二、实验要求
1. 该实验模拟的是非抢占式静态优先权进程调度算法;
2. 优先权始终保持不变;
3. 一旦进入 CPU 便运行到结束;
4. FCFS 只考虑到达时间进 CPU;
5. SJF 认为到达时间相同;
三、实验步骤
先选择对应的调度算法,将所有进程按照对应的调度算法所求的优先级在就绪队列上排队,队头进程进 CPU 运行,如果该进程总服务时间等于在 CPU 上的运行时间,那么进程结束,直到所有进程均运行完毕。
➢ 1. 选择调度算法,包括短进程优先和先来先服务;
➢ 2. 假定所有进程都是就绪状态,按照所选调度算法所得优先级进就绪排队,队列中队头进程优先级最高,队尾优先级最低;
➢ 3. 就绪队列队头的进程进 CPU,运行这个进程;
➢ 4. 如果进程在 CPU 上运行时间和服务时间相等,则该进程结束;
➢ 5. 每次进程进 CPU 时都要输出一次所有进程信息。
四、核心代码
先来先服务算法代码:
void FCFS(PCB pro[], int num) {
int time,done_time;
int i,count,tt,pronum;
float sum_T_time,sum_QT_time;
PCB *curpro,*temp_PCB;
printf("\n\t\t\t\t\t先来先服务算法进程调度模拟\n\n");
printf("\t————————————————————————————————————————————————\n");
count=0;
PCB pro2[100];
sortWithEnterTime(pro, num);
PCBQueue* queue = (PCBQueue*)malloc(sizeof(PCBQueue));
Queueinit(queue);
EnterQueue(queue, &pro[0]);
time = pro[0].arrivetime;
pronum = 1;
sum_T_time = 0, sum_QT_time = 0;
while (queue->size > 0) {
curpro = poll(queue);
if (time < curpro->arrivetime){
time = curpro->arrivetime;
}
done_time = time + curpro->running_time;
curpro->start_time=time;
curpro->done_time=done_time;
curpro->zztime = done_time - curpro->arrivetime;
curpro->dqzztime = curpro->zztime / curpro->running_time;
sum_T_time += curpro->zztime;
sum_QT_time += curpro->dqzztime;
for (tt = time; tt <= done_time && pronum < num; tt++) {
if (tt >= pro[pronum].arrivetime) {
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
CopyProgram(&pro2[count],curpro);
PrintRunningprogram(&pro2[count]);
count++;
if(queue->size!=0) {
printf("\t就绪队列:\n");
printf("\t————————————————————————————————————————————————\n");
printf("\t进程 到达时间 服务时间\n");
temp_PCB=queue->firstProg->next;
for(i=queue->size; i>0; i--) {
printf("\t%s\t%d\t%d\n",temp_PCB->name,temp_PCB->arrivetime,temp_PCB->running_time);
temp_PCB=temp_PCB->next;
}
printf("\t————————————————————————————————————————————————\n");
printf("\n\n\n");
} else {
printf("\t无进程处于就绪状态!\n");
printf("\t————————————————————————————————————————————————\n\n\n");
}
time += curpro->running_time;
if (queue->size == 0 && pronum < num) {
EnterQueue(queue, &pro[pronum]);
pronum++;
}
}
PrintSortOfRunningprogram(pro2,count);
printf("\t平均周转时间为:%.2f\n", sum_T_time /num);
printf("\t平均带权周转时间为:%.2f\n",sum_QT_time/num);
}
短作业优先代码:
void SJF(PCB pro[],int num) {
int time,done_time;
float sum_T_time,sum_QT_time;
int i,pronum;
PCBQueue *ready_queue;
PCB *curpro,pro1[MAXSIZE];
printf("\n\t\t\t\t\t短作业优先算法进程调度模拟\n\n");
printf("\t————————————————————————————————————————————————\n");
sortWithEnterTime(pro, num);
ready_queue = (PCBQueue*)malloc(sizeof(PCBQueue));
if(!ready_queue) {
printf("分配就绪队列头结点空间失败!");
exit(1);
}
Queueinit(ready_queue);
EnterQueueOfRuntime(ready_queue,&pro[0]);
time = pro[0].arrivetime;
pronum = 1;
sum_T_time = 0, sum_QT_time = 0;
i=0;
while(ready_queue->size>0) {
curpro=poll(ready_queue);
if(time<curpro->arrivetime) {
time=curpro->arrivetime;
}
done_time=time+curpro->running_time;
curpro->start_time=time;
curpro->done_time=done_time;
curpro->zztime = done_time - curpro->arrivetime;
curpro->dqzztime = curpro->zztime / curpro->running_time;
PrintRunningprogram(curpro);
CopyProgram(&pro1[i],curpro);
i++;
sum_T_time += curpro->zztime;
sum_QT_time += curpro->dqzztime;
while(pronum<num) {
if(pro[pronum].arrivetime<=done_time) {
EnterQueueOfRuntime(ready_queue,&pro[pronum]);
pronum++;
} else {
break;
}
}
PrintReadyqueue(ready_queue);
time=done_time;
if(ready_queue->size==0&&pronum<num) {
EnterQueueOfRuntime(ready_queue,&pro[pronum]);
pronum++;
}
}
PrintSortOfRunningprogram(pro1,num);
printf("\t平均周转时间为:%.2f\n", sum_T_time / num);
printf("\t平均带权周转时间为:%.2f\n",sum_QT_time/num);
}
主函数代码:
int main() {
int n, t = 1;
int proNum, choice;
PCB pro[MAXSIZE],temp_pro[MAXSIZE];
printf("\n\n\t\t\t\t\t<<-------------进程初始化----------——>>\n");
printf("\t\t\t\t\t请输入进程的个数:");
scanf("%d", &proNum);
inputProgram(pro, proNum);
while (t) {
menu();
memcpy(temp_pro, pro, (sizeof(pro) / sizeof(pro[0])) * sizeof(PCB));
scanf("%d", &n);
while (n <= 0 || n > 3 ){
printf("\t\t\t指令不正确,请重新输入指令: ");
scanf("%d", &n);
}
system("cls");
switch (n) {
case 1: {
FCFS(temp_pro, proNum);
break;
}
case 2: {
SJF(temp_pro, proNum);
break;
}
case 3: {
t = 0;
break;
}
}
getchar();
printf("\n\t按任意键继续.......");
getchar();
system("cls");
}
system("cls");
printf("\n\n\t\t\t\t\t您已成功退出系统!!!\n");
return 0;
}
五、记录与处理
(1)先来先服务调度算法(FCFS)
选择先来先服务调度算法(FCFS)按照作业/进程到达的先后顺序进行服务的,主要从“公平”的角度考虑。
执行后结果为:
(2) 短作业优先调度算法(SJF)
输入的进程数据如下:
执行后结果为:
六、思考
1. 先来先服务算法:指的是按照作业/进程到达的先后顺序进行服务的,主要从“公平”的角度考虑。用于作业调度时,考虑的是哪个作业先到达后备队列;用于进程调度时,考虑的是哪个进程先到达就绪队列,是非抢占式算法,不会导致饥饿(某进程/作业长时间得不到服务)
优点:公平、算法实现简单
缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好,即FCFS算法对长作业有利,对短作业不利
2. 短作业优先算法追求最少的平均等待时间,最少的平均周转时间,最少的平均带权周转时间,即让最短的作业/进程得到服务(最短为服务时间最短),既可用于作业调度,也可用于进程调度。用于进程调度时称为“短进程优先”(SPF)算法。SJF和SPF是非抢占式算法,但是也有抢占式的版本——最短剩余时间优先法。
优点:“最短的”平均等待时间,平均周转时间
缺点:对长作业不利。可能产生饥饿现象。
3. 此实验代码中增加了一个菜单选项的界面,在执行代码的时候可以通过菜单选项选择执行先来先服务或者短进程优先调度算法,增加了交互性。
4. 优先级调度算法既可以应用于高级调度(作业调度)也可以应用于低级调度(进程调度),还可用于实时系统。高级调度时,优先数调度算法每次从后备作业队列中选择优先级最高的作业调入内存,为其分配相应的资源并创建进程放入到进程就绪队列中。低级调度时,优先级调度算法每次从进程就绪队列中选择优先级最高的进程为其分配CPU而投入运行。如果有多个优先级最高的作业/进程,则可结合先来先服务或短作业/短进程优先调度策略。
按照进程的优先权大小来调度,使高优先权进程得到优先处理的调度策略称为优先权调度算法。进程的优先权的设置可以是静态的,也可以是动态的。
对于加入进程优先级,可以在代码里面对么一个进程定义一个优先级变量,处理进程作业时按照优先级变量的大小来先后处理进程作业,优先级大的先执行。
七、完整报告和成果文件提取链接
链接:https://pan.baidu.com/s/1UbP6729pCluscVW0_9oI8w?pwd=1xki
提取码:1xki