操作系统进程调度实验报告

一、实验目的

        用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解

二、实验类别

        综合性实验。综合高级语言编程、进程调度模型、进程调度算法及数据结构等多方面的知识

三、实验示例

例题: 设计一个有 N个进程共行的进程调度程序

进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。

每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。

进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输

入的时间。

  进程的运行时间以时间片为单位进行计算。

  每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。

  就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。

  如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。

  每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。   

重复以上过程,直到所要进程都完成为止。

调度算法的流程图如下 :

四、源代码

#include "stdio.h" 
#include <stdlib.h> 
#include <conio.h> 
#define getpch(type) (type*)malloc(sizeof(type)) //分配type类型大小的空间
#define NULL 0 
struct pcb { /* 定义进程控制块PCB */ 
char name[10]; //进程名
char state; //进程状态
int super; //进程优先级
int ntime; //进程总共需要运行的时间
int rtime; //进程已经运行的时间
struct pcb* link; //指向后继节点的指针
}*ready=NULL,*p;  //ready指针永远指向队列的第一个进程
typedef struct pcb PCB; 
  
sort() /* 建立对进程进行优先级排列函数*/ 
{ 
PCB *first, *second; // 指针second指向队列中当前处理的进程,指针first指向second的前驱节点,指针p指向准备插入队列的进程;
int insert=0; //判断是否
if((ready==NULL)||((p->super)>(ready->super))) /*优先级最大者,插入队首*/ 
{ 
p->link=ready; //p指向的进程优先级最高,要成为队列中新的队首节点,即ready要修改指向p;
ready=p; 
} 
else /* 如果队列有至少一个进程,则进程比较优先级,插入适当的位置中*/ 
{ 
first=ready; // first指向队首节点;
second=first->link; // second指向第2个节点;
while(second!=NULL) //如果有第2个节点,即队列至少有2个节点;
{ 
if((p->super)>(second->super)) /*若插入进程比当前进程优先数大,*/ 
{ /*插入到当前进程前面*/ //p指向的进程要插入到first和sencond之间,修改指针;
p->link=second; 
first->link=p; 
second=NULL; //找到了进程插入的位置,把second设为NULL,退出while循环;
insert=1; //insert为1表示p指向的进程插入在两个进程之间;
} 
else /* 插入进程优先数最低,则插入到队尾*/ 
{ 
first=first->link; // 此时first指向原队列最后一个进程;
second=second->link; //此时second为NULL;
} 
} 
if(insert==0) first->link=p; // insert为0表示p指向的进程插入到队尾
} 
}

input() /* 建立进程控制块函数*/ 
{ 
int i,num; 
//clrscr(); /*清屏*/ 
printf("\n 请输入进程号?"); //输入需要调度的进程数量
scanf("%d",&num); 
for(i=0;i<num;i++) //依次输入每个进程控制块的信息;
{ 
printf("\n 进程号No.%d:\n",i); 
p=getpch(PCB); 
printf("\n 输入进程名:"); 
scanf("%s",p->name); 
printf("\n 输入进程优先数:"); 
scanf("%d",&p->super); 
printf("\n 输入进程运行时间:"); 
scanf("%d",&p->ntime); 
printf("\n"); 
p->rtime=0;p->state='w'; 
p->link=NULL; 
sort(); /* 调用sort函数*/ //把新创建的进程按优先级插入到队列中;
} 
} 
int space() //获取当前队列的长度,即需要调度的进程个数;
{ 
int l=0; PCB* pr=ready; //pr指向队列第一个进程,即对首进程
while(pr!=NULL) //依次遍历整个队列,计算长度
{ 
l++; //是字符l,不是数字1,代表队列长度;
pr=pr->link;
} 
return(l); 
} 
disp(PCB * pr) /*建立进程显示函数,用于显示当前进程的信息*/ 
{ 
printf("\n qname \t state \t super \t ndtime \t runtime \n"); 
printf("|%s\t",pr->name); 
printf("|%c\t",pr->state); 
printf("|%d\t",pr->super); 
printf("|%d\t",pr->ntime); 
printf("|%d\t",pr->rtime); 
printf("\n"); 
}
check() /* 建立进程查看函数 */ //查看当前队列中每个进程信息
{ 
PCB* pr; 
printf("\n **** 当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/ 
disp(p); 
pr=ready; // pr指向队列对首进程
printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/ 
while(pr!=NULL) //循环遍历队列中每个进程
{ 
disp(pr); 
pr=pr->link; 
} 
} 
destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/ 
{ 
printf("\n 进程 [%s] 已完成.\n",p->name); 
free(p); 
} 
running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/ 
{ 
(p->rtime)++; //p指向当前运行进程,即从原队列中的对首进程,运行次数加1,rtime表示已运行的时间片;
if(p->rtime==p->ntime) //如果进程需要运行总时间ntime和已运行时间rtime相等,表示该进程已经运行完毕,需要撤销;
destroy(); /* 调用destroy函数*/ 
else //如果该进程没有运行完毕,则使它的优先级减1,状态变为就绪,重新按优先级顺序插入到队列中;
{ 
(p->super)--; 
p->state='w'; 
sort(); /*调用sort函数*/ 
} 
} 
main() /*主函数*/ 
{ 
int len,h=0; //len:队列进程的个数;h:进程调度的时间片次数
char ch; // 获取getchar()函数的字符
input(); //输入要处理进程控制块信息
len=space(); //当前进程队列的长度,即要处理的进程数量
while((len!=0)&&(ready!=NULL)) //若队列不为空,即还有进程需要处理;
{ 
ch=getchar(); //从键盘获取字符
h++; // h:进程执行的时间片次数序号
printf("\n The execute number:%d \n",h); //
p=ready;  // ready永远指向队列的对首进程,p此时也指向队列的对首进程,但该对首进程需要出队列以便运行,;
ready=p->link; //原队列的第2个进程成为新的对首进程
p->link=NULL; //原对首进程出队列后,没有后继;
p->state='R'; //原对首进程出队列后状态变为执行;
check(); //查看当前队列中所有进程的信息,即原对首进程出队列后
running();//原对首进程运行
printf("\n 按任一键继续......"); 
ch=getchar();//从键盘获取字符
} 
printf("\n\n 进程已经完成.\n"); 
ch=getchar();//从键盘获取字符
}

五、运行截图

 六、报告总结

        通过本次实验,进程动态调度的过程与人工分析的结果一致,基本达到预期的目标。通过用户自己定义进程号、进程名、进程优先数、进程运行时间。优先数高的进程先进入运行状态,其他进程则为就绪状态。若优先数高的进程运行一个时间片后仍需运行,则进入就绪状态,该进程优先数-1。若进程运行一个时间片后,已经达成所需要的运行时间,则该进程完成,进入完成状态。如果就绪队列里存有多个优先数相同的进程,则根据进程号先来先得的原则运行。

 

 

 

  • 7
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
一、实验目的 本实验旨在通过模拟实现多种进程调度算法,掌握进程调度的基本概念和操作方法,加深对操作系统的理解。 二、实验内容 1. 实现进程调度程序,并模拟 FCFS、SJF、RR、优级调度等算法; 2. 分别用不同的实际应用场景,比如 CPU 密集型和 I/O 密集型任务,测试不同调度算法的效率和公平性; 3. 统计每种算法的平均等待时间、平均周转时间和平均响应时间,比较它们的优缺点。 三、实验步骤 1. 设计进程控制块 PCB 的数据结构,包括进程标识符 PID、进程状态 status、进程级 priority、进程所需 CPU 时间 need_time、进程已占用 CPU 时间 used_time、进程到达时间 arrival_time、进程等待时间 wait_time、进程周转时间 turnover_time、进程响应时间 response_time 等字段。 2. 实现进程调度程序,包括 FCFS、SJF、RR、优级调度等算法。其中,FCFS 算法按照进程到达时间的后顺序依次执行,SJF 算法按照进程所需 CPU 时间的短长顺序执行,RR 算法按照时间片大小分配 CPU 时间,并循环执行所有进程,优级调度算法按照进程级的高低顺序执行。 3. 编写测试程序,模拟不同的实际应用场景,比如 CPU 密集型和 I/O 密集型任务。对于 CPU 密集型任务,需要让进程的 need_time 大于 arrival_time,以便测试 SJF 和优级调度算法的效果;对于 I/O 密集型任务,需要设置进程的 I/O 操作,以便测试 RR 算法的效果。 4. 运行测试程序,记录每个进程的到达时间、需要 CPU 时间、优级等信息,并根据不同的调度算法进行模拟,计算出每个进程的等待时间、周转时间和响应时间。 5. 对不同的调度算法进行比较,分析其优缺点,并统计平均等待时间、平均周转时间和平均响应时间。 四、实验结果 1. 设计进程控制块 PCB 的数据结构如下: ```c typedef struct PCB { int pid; // 进程标识符 int status; // 进程状态 int priority; // 进程级 int need_time; // 进程所需 CPU 时间 int used_time; // 进程已占用 CPU 时间 int arrival_time; // 进程到达时间 int wait_time; // 进程等待时间 int turnover_time; // 进程周转时间 int response_time; // 进程响应时间 struct PCB *next; // 链表指针 } PCB; ``` 2. 实现进程调度程序,包括 FCFS、SJF、RR、优级调度等算法。具体代码如下: ```c // FCFS 调度算法 void fcfs(PCB *head) { PCB *p = head->next; int time = p->arrival_time; // 当前时间 while (p != NULL) { // 计算等待时间、周转时间和响应时间 p->wait_time = time - p->arrival_time; p->turnover_time = p->wait_time + p->need_time; p->response_time = p->wait_time; // 更新当前时间 time += p->need_time; // 处理下一个进程 p = p->next; } } // SJF 调度算法 void sjf(PCB *head) { PCB *p = head->next; int time = p->arrival_time; // 当前时间 while (p != NULL) { // 查找需要执行的进程 PCB *q = p->next; while (q != NULL) { if (q->arrival_time > time) { break; } if (q->need_time < p->need_time) { PCB tmp = *p; *p = *q; *q = tmp; } q = q->next; } // 计算等待时间、周转时间和响应时间 p->wait_time = time - p->arrival_time; p->turnover_time = p->wait_time + p->need_time; p->response_time = p->wait_time; // 更新当前时间 time += p->need_time; // 处理下一个进程 p = p->next; } } // RR 调度算法 void rr(PCB *head, int quantum) { PCB *p = head->next; int time = p->arrival_time; // 当前时间 while (p != NULL) { // 计算等待时间、周转时间和响应时间 p->wait_time = time - p->arrival_time; p->response_time = p->wait_time; // 分配时间片 int remain_time = p->need_time; while (remain_time > 0) { if (remain_time <= quantum) { // 进程执行完毕 time += remain_time; p->used_time += remain_time; remain_time = 0; } else { // 时间片用完了 time += quantum; p->used_time += quantum; remain_time -= quantum; // 将进程移到队列尾部 PCB *q = p->next; while (q != NULL) { if (q->arrival_time > time) { break; } q = q->next; } PCB tmp = *p; tmp.next = q; *p = *p->next; p->next = tmp.next; } } // 计算周转时间 p->turnover_time = p->wait_time + p->used_time; // 处理下一个进程 p = p->next; } } // 优级调度算法 void priority(PCB *head) { PCB *p = head->next; int time = p->arrival_time; // 当前时间 while (p != NULL) { // 查找需要执行的进程 PCB *q = p->next; while (q != NULL) { if (q->arrival_time > time) { break; } if (q->priority < p->priority) { PCB tmp = *p; *p = *q; *q = tmp; } q = q->next; } // 计算等待时间、周转时间和响应时间 p->wait_time = time - p->arrival_time; p->turnover_time = p->wait_time + p->need_time; p->response_time = p->wait_time; // 更新当前时间 time += p->need_time; // 处理下一个进程 p = p->next; } } ``` 3. 编写测试程序,模拟不同的实际应用场景。对于 CPU 密集型任务,设置进程的 need_time 大于 arrival_time;对于 I/O 密集型任务,设置进程的 I/O 操作。具体代码如下: ```c // 生成测试数据 void gen_data(PCB *head, int type) { srand(time(NULL)); int pid = 1; PCB *p = head; while (p->next != NULL) { p = p->next; } for (int i = 0; i < MAX_NUM; i++) { pid++; PCB *q = (PCB*)malloc(sizeof(PCB)); q->pid = pid; q->status = READY; q->priority = rand() % 5 + 1; q->need_time = rand() % 10 + 1; if (type == CPU_INTENSIVE) { q->arrival_time = rand() % MAX_NUM; while (q->need_time <= q->arrival_time) { q->need_time = rand() % 10 + 1; } } else if (type == IO_INTENSIVE) { q->arrival_time = rand() % MAX_NUM; q->need_time = rand() % 5 + 1; if (rand() % 2 == 0) { q->io_time = rand() % q->need_time + 1; } else { q->io_time = 0; } } q->used_time = 0; q->wait_time = 0; q->turnover_time = 0; q->response_time = 0; q->next = NULL; p->next = q; p = p->next; } } // 显示测试数据 void show_data(PCB *head) { PCB *p = head->next; printf("PID\tStatus\tPriority\tNeed Time\tArrival Time\tIO Time\n"); while (p != NULL) { printf("%d\t%d\t%d\t\t%d\t\t%d\t\t%d\n", p->pid, p->status, p->priority, p->need_time, p->arrival_time, p->io_time); p = p->next; } } // 模拟 I/O 操作 int do_io(PCB *head, PCB *p) { if (p->io_time > 0) { p->io_time--; if (p->io_time == 0) { // I/O 完成,将进程移到队列尾部 PCB *q = p->next; while (q != NULL) { if (q->arrival_time > p->arrival_time) { break; } q = q->next; } PCB tmp = *p; tmp.next = q; *p = *p->next; p->next = tmp.next; return 1; } } return 0; } // 测试 FCFS 调度算法 void test_fcfs(PCB *head) { printf("FCFS 调度算法:\n"); fcfs(head); show_result(head); } // 测试 SJF 调度算法 void test_sjf(PCB *head) { printf("SJF 调度算法:\n"); sjf(head); show_result(head); } // 测试 RR 调度算法 void test_rr(PCB *head, int quantum) { printf("RR 调度算法(quantum=%d):\n", quantum); PCB *p = head->next; int time = p->arrival_time; // 当前时间 while (p != NULL) { // 计算等待时间、响应时间和周转时间 p->wait_time = time - p->arrival_time; p->response_time = p->wait_time; // 分配时间片 int remain_time = p->need_time; while (remain_time > 0) { if (remain_time <= quantum) { // 进程执行完毕 time += remain_time; p->used_time += remain_time; remain_time = 0; } else { // 时间片用完了,进行 I/O 操作 time += quantum; p->used_time += quantum; remain_time -= quantum; if (do_io(head, p)) { break; } } } // 计算周转时间 p->turnover_time = p->wait_time + p->used_time; // 处理下一个进程 p = p->next; } show_result(head); } // 测试优级调度算法 void test_priority(PCB *head) { printf("优级调度算法:\n"); priority(head); show_result(head); } // 显示测试结果 void show_result(PCB *head) { PCB *p = head->next; double total_wait_time = 0, total_turnover_time = 0, total_response_time = 0; printf("PID\tStatus\tPriority\tNeed Time\tArrival Time\tIO Time\tWait Time\tTurnover Time\tResponse Time\n"); while (p != NULL) { printf("%d\t%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n", p->pid, p->status, p->priority, p->need_time, p->arrival_time, p->io_time, p->wait_time, p->turnover_time, p->response_time); total_wait_time += p->wait_time; total_turnover_time += p->turnover_time; total_response_time += p->response_time; p = p->next; } double avg_wait_time = total_wait_time / MAX_NUM; double avg_turnover_time = total_turnover_time / MAX_NUM; double avg_response_time = total_response_time / MAX_NUM; printf("平均等待时间:%lf,平均周转时间:%lf,平均响应时间:%lf\n", avg_wait_time, avg_turnover_time, avg_response_time); } ``` 4. 运行测试程序,记录每个进程的到达时间、需要 CPU 时间、优级等信息,并根据不同的调度算法进行模拟,计算出每个进程的等待时间、周转时间和响应时间。具体代码如下: ```c int main() { // 初始化进程链表 PCB *head = (PCB*)malloc(sizeof(PCB)); head->next = NULL; // 生成测试数据 gen_data(head, CPU_INTENSIVE); // 显示测试数据 show_data(head); // 测试 FCFS 调度算法 test_fcfs(head); // 测试 SJF 调度算法 test_sjf(head); // 测试 RR 调度算法 test_rr(head, 2); // 测试优级调度算法 test_priority(head); // 释放内存 PCB *p = head; while (p != NULL) { PCB *q = p->next; free(p); p = q; } return 0; } ``` 五、实验分析 本实验模拟了 FCFS、SJF、RR、优级调度等四种进程调度算法,并通过测试程序模拟了不同的实际应用场景,比如 CPU 密集型和 I/O 密集型任务。根据测试结果,可以分析出每种算法的优缺点。 1. FCFS 调度算法 FCFS 调度算法按照进程到达时间的后顺序依次执行,适用于 CPU 密集型任务。优点是实现简单,没有额外的开销,但缺点是可能导致长作业等待时间过长,无法满足实时性要求。 2. SJF 调度算法 SJF 调度算法按照进程所需 CPU 时间的短长顺序执行,适用于 CPU 密集型任务。优点是平均等待时间最短,但缺点是难以预测每个进程的需要时间,可能导致长作业饥饿。 3. RR 调度算法 RR 调度算法按照时间片大小分配 CPU 时间,并循环执行所有进程,适用于 CPU 密集型和 I/O 密集型任务。优点是公平性好,长作业不会饥饿,但缺点是时间片过小会增加上下文切换的开销,时间片过大会使得响应时间变长。 4. 优级调度算法级调度算法按照进程级的高低顺序执行,适用于 I/O 密集型任务。优点是可以满足实时性要求,但缺点是可能导致低优进程饥饿,需要设置合理的优级和调整策略。 六、实验总结 本实验通过模拟实现多种进程调度算法,深入理解了操作系统的基本概念和操作方法,加深了对操作系统的理解。实验中还通过测试程序模拟了不同的实际应用场景,比较

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

henry594小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值