目录
一、实验目的
1、掌握高优先权调度算法
2、理解时间片、优先权、抢占等基本概念。
二、实验要求
1. 优先权属于静态优先权;
2. 进入 CPU 运行一个时间片;
3. 考虑事先给定优先权和短进程优先两种情况;
4. 考虑到达时间不同。
三、实验步骤
1. 创建多个进程,假定所有进程都是就绪状态,根据进程的到达时间进就绪队列,选择调度算法;
2. 按照所选调度算法,使进程在就绪队列中排序,队列中队头进程优先级最高,队尾优先级最低;
3. 初始状态直接让队头进程进 CPU,运行 1 个时间片;
4. 如果进程在 CPU 上运行时间和服务时间相等,则该进程不需进就绪队列,否则,进程进就绪队列;同时,根据进程的到达时间看是否有进程进就绪队列;
5. 每次调度时都要输出一次所有进程信息。
四、核心代码
void CopyProgram(PCB *pro1,PCB *pro2) {
memcpy(pro1->name,pro2->name,sizeof(pro2->name));
pro1->arrivetime=pro2->arrivetime;
pro1->running_time=pro2->running_time;
pro1->priority=pro2->priority;
pro1->start_time=pro2->start_time;
pro1->done_time=pro2->done_time;
pro1->zztime=pro2->zztime;
pro1->dqzztime=pro2->dqzztime;
}
void Queueinit(PCBQueue* queue) {
if (queue == NULL) {
return;
}
queue->size = 0;
queue->LastProg = (PCB*)malloc(sizeof(PCB));
queue->LastProg->next=NULL;//注意加了此句
queue->firstProg = queue->LastProg;
}
void EnterQueue(PCBQueue* queue, PCB* pro) {
//加入进程队列
queue->LastProg->next = (PCB*)malloc(sizeof(PCB));
queue->LastProg = queue->LastProg->next;
queue->LastProg->arrivetime = pro->arrivetime;
memcpy(queue->LastProg->name, pro->name, sizeof(pro->name));
queue->LastProg->priority = pro->priority;
queue->LastProg->running_time = pro->running_time;
queue->LastProg->copyRunning_time = pro->copyRunning_time;
queue->LastProg->start_time = pro->start_time;
queue->LastProg->next=NULL;//注意加了此句
queue->size++;
}
PCB* poll(PCBQueue* queue) {
PCB *temp;
temp = queue->firstProg->next;
if (temp == queue->LastProg) {
queue->LastProg = queue->firstProg;
queue->LastProg->next=NULL;//注意加了此句
queue->size--;
return temp;
}
queue->firstProg->next = queue->firstProg->next->next;
queue->size--;
return temp;
}
void sortWithEnterTime(PCB pro[], int num) { //将进程按到达时间(arrivetime)全部排序
int i,j;
PCB temp;
for (i = 1; i < num; i++) {
for (j = 0; j < num - i; j++) {
if (pro[j].arrivetime > pro[j + 1].arrivetime) {
temp = pro[j];
pro[j] = pro[j + 1];
pro[j + 1] = temp;
}
}
}
}
void EnterQueueOfRuntime(PCBQueue *ready_queue,PCB *program) { //按进程的运行时间,找到就绪队列中的相应位置并插入进去
PCB *p,*q;
p=ready_queue->firstProg->next;
q=ready_queue->firstProg;
while(p) {
if(p->running_time>program->running_time) {
program->next=p;
q->next=program;
break;
}
q=p;
p=p->next;
}
if(!p) { //如果就绪队列为空或该进程的运行时间最长,则将其插入到队尾
ready_queue->LastProg->next=program;
ready_queue->LastProg=program;
program->next=NULL;
}
ready_queue->size++;
}
void EnterQueueOfPriority(PCBQueue *ready_queue,PCB *program) {
PCB *p,*q;
p=ready_queue->firstProg->next;
q=ready_queue->firstProg;
while(p) {
if(p->priority<program->priority) { //优先级大的先执行
program->next=p;
q->next=program;
break;
}
q=p;
p=p->next;
}
if(!p) {
ready_queue->LastProg->next=program;
ready_queue->LastProg=program;
program->next=NULL;
}
ready_queue->size++;
}
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; // sum_T_time 记录总的周转时间 ,sum_QT_time 记录总的加权周转时间
while (queue->size > 0) {
curpro = poll(queue); //从进程队列中取出一个进程
if (time < curpro->arrivetime){
time = curpro->arrivetime;
}
done_time = time + curpro->running_time; // done_time 为该进程的结束时间(开始时间+CPU运行时间)
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_T_time 总的周转时间更新
sum_QT_time += curpro->dqzztime; // sum_T_time 总的带权周转时间更新
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\t%d\n",temp_PCB->name,temp_PCB->arrivetime,temp_PCB->running_time,temp_PCB->priority);
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);
//Print(pro2,count);
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 > 4) {
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: {
HPF(temp_pro, proNum);
break;
}
case 4: {
t=0;
break;
}
}
getchar();
printf("\n\t按任意键继续.......");
getchar();
system("cls");
}
system("cls");
printf("\n\n\t\t\t\t\t您已成功退出系统!!!\n");
return 0;
}
五、记录与处理
输入的进程数据如下:
选择第三个:高优先级算法
按照高优先级进行输出结果:
六、思考
高优先权调度算法的弊端是什么?
高优先权调度算法是一种在计算机系统中用于进程或作业调度的算法,它根据进程的优先权(或优先级)来决定执行顺序。优先权高的进程或作业会被优先执行,而优先权低的则会被推迟执行。然而,这种算法也存在一些弊端:
1.低优先级进程饥饿:在高优先权调度算法下,如果系统中存在大量高优先级的进程,低优先级的进程可能会被持续推迟执行,导致它们的响应速度变慢,甚至长时间得不到执行,这种现象被称为“饥饿”。
2.恶意进程或病毒的影响:恶意进程或病毒可能会通过提高自己的优先权来占用系统资源,导致正常进程无法得到执行。这种情况下,系统的安全性和稳定性会受到影响。
3.可能导致系统资源浪费:如果高优先级的进程执行了很短的时间就放弃处理机,那么系统会频繁地进行进程切换,这会导致系统资源的浪费,降低系统的整体效率。
4.未考虑作业的紧迫程度:高优先权调度算法在决定执行顺序时,可能未充分考虑作业的紧迫程度,因此不能保证紧迫性作业会被及时处理。
为了克服这些弊端,可以采用一些优化措施,例如设置进程的最大执行时间以避免长时间占用CPU资源,或者采用动态优先级调度算法,根据进程的实际执行情况来动态调整进程的优先级。此外,还可以考虑引入高响应比优先调度算法,以更全面地考虑进程的执行需求。
综上所述,虽然高优先权调度算法能确保高优先级进程或作业得到优先处理,但也存在可能导致低优先级进程饥饿、受恶意进程或病毒影响、系统资源浪费以及未考虑作业紧迫程度等弊端。因此,在设计和实施此类算法时,需要充分考虑这些因素,并采取适当的优化措施。
七、完整报告和成果文件提取链接
链接:https://pan.baidu.com/s/1UbP6729pCluscVW0_9oI8w?pwd=1xki
提取码:1xki