实验二--单处理器系统的进程调度
- 格式:docx
- 大小:81.16 KB
- 文档页数:17
五邑大学实验报告操作系统课程2016~2017年度第1学期实验题目:进程调度院系:计算机学院班级: 140801学号: 3114002472姓名:黄凯鑫任课教师:白明成绩评定:实验二题目:进程调度完成日期:2016年12 月11 日1、实验目的(1)设计一个有n个进程工行的进程调度程序。
每个进程由一个进程控制块(PCB)表示。
进程控制块通常应包含下述信息:进程名、进程优先数、进程需要运行的时间、占用CPU的时间以及进程的状态等,且可按调度算法的不同而增删。
(2)调度程序应包含2~3种不同的调度算法,运行时可任意选一种,以利于各种算法的分析比较。
(3)系统应能显示或打印各进程状态和参数的变化情况,便于观察诸进程的调度过程2、实验内容(1)编制和调试示例给出的进程调度程序,并使其投入运行。
(2)自行设计或改写一个进程调度程序,在相应机器上调试和运行该程序,其功能应该不亚于示例。
(3)直观地评测各种调度算法的性能。
3、算法设计算法:(1) 优先数法。
进程就绪链按优先数大小从高到低排列,链首进程首先投入运行。
每过一个时间片,运行进程所需运行的时间片数减1,说明它已运行了一个时间片,优先数也减3,理由是该进程如果在一个时间片中完成不了,优先级应该降低一级。
接着比较现行进程和就绪链链首进程的优先数,如果仍是现行进程高或者相同,就让现行进程继续进行,否则,调度就绪链链首进程投入运行。
原运行进程再按其优先数大小插入就绪链,且改变它们对应的进程状态,直至所有进程都运行完各自的时间片数。
(2) 简单轮转法。
进程就绪链按各进程进入的先后次序排列,进程每次占用处理机的轮转时间按其重要程度登入进程控制块中的轮转时间片数记录项(相当于优先数法的优先数记录项位置)。
每过一个时间片,运行进程占用处理机的时间片数加1,然后比较占用处理机的时间片数是否与该进程的轮转时间片数相等,若相等说明已到达轮转时间,应将现运行进程排到就绪链末尾,调度链首进程占用处理机,且改变它们的进程状态,直至所有进程完成各自的时间片。
操作系统实验报告进程调度操作系统实验报告:进程调度引言操作系统是计算机系统中最核心的软件之一,它负责管理和调度计算机的资源,提供良好的用户体验。
在操作系统中,进程调度是其中一个重要的功能,它决定了进程的执行顺序和时间片分配,对于提高计算机系统的效率和响应能力至关重要。
本篇实验报告将重点介绍进程调度的相关概念、算法和实验结果。
一、进程调度的概念进程调度是操作系统中的一个重要组成部分,它负责决定哪个进程可以使用CPU,并为其分配执行时间。
进程调度的目标是提高系统的吞吐量、响应时间和公平性。
在多道程序设计环境下,进程调度需要考虑多个进程之间的竞争和协作,以实现资源的合理利用。
二、进程调度算法1. 先来先服务调度(FCFS)先来先服务调度算法是最简单的进程调度算法之一,它按照进程到达的顺序进行调度,即先到达的进程先执行。
这种算法的优点是公平性高,缺点是无法适应长作业和短作业混合的情况,容易产生"饥饿"现象。
2. 最短作业优先调度(SJF)最短作业优先调度算法是根据进程的执行时间来进行调度的,即执行时间最短的进程先执行。
这种算法的优点是能够最大程度地减少平均等待时间,缺点是无法适应实时系统和长作业的情况。
3. 时间片轮转调度(RR)时间片轮转调度算法是一种抢占式调度算法,它将CPU的执行时间划分为固定大小的时间片,并按照轮转的方式分配给各个进程。
当一个进程的时间片用完后,它将被挂起,等待下一次调度。
这种算法的优点是能够保证每个进程都能够获得一定的执行时间,缺点是无法适应长作业和短作业混合的情况。
4. 优先级调度(Priority Scheduling)优先级调度算法是根据进程的优先级来进行调度的,优先级高的进程先执行。
这种算法的优点是能够根据进程的重要性和紧急程度进行灵活调度,缺点是可能会导致低优先级的进程长时间等待。
三、实验结果与分析在实验中,我们使用了不同的进程调度算法,并对其进行了性能测试。
实验项目二进程调度一、实验内容、目标及要求(一)实验内容1、设计可用于该实验的进程控制块,进程控制块至少包括进程号、状态和要求服务时间;2、动态或静态创建多个进程;3、模拟操作系统四种进程调度算法中的任意一种。
4、调度所创建的进程并显示调度结果。
(二)实验目标1、加深进程概念的理解;2、掌握进程状态转变;3、掌握进程调度策略。
(三)实验要求1、编写程序完成实验内容;2、在实验报告中画出程序流程图;3、撰写实验报告。
二、实验准备(一)运行环境说明计算机、Windows95/98/Me/2000/XP操作系统(需要能够上网)、Microsoft Visual C++、“记事本”程序。
(二)基础数据设置及说明计算机、Windows95/98/Me/2000/XP操作系统(需要能够上网)、Microsoft Visual C++6.0、“记事本”程序,均能正常运行。
三、实验原理(一)进程概念:1、进程是程序的一次执行。
2、进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
3、进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
(二)进程状态:进程执行时的间断性决定了进程可能具有多种状态。
事实上,运行中的进程可能具有以下三种基本状态。
1、就绪状态当进程已分配到除CPU以外的所有必要资源后,只要再获得CPU,便可立即执行,进程这时的状态称为就绪状态。
在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。
2、执行状态进程已获得CPU,其程序正在执行。
在单处理机系统中,只有一个进程处于执行状态;在多处理机系统中,则有多个进程处于执行状态。
3、阻塞状态正在执行的进程由于发生某事件而暂时无法继续执行时,便放弃处理机而处于暂停状态,亦即进程的执行受到阻塞,把这种暂停状态称为阻塞状态,有时也称为等待状态或封锁状态。
致使进程阻塞的典型事件有:请求I/O,申请缓冲空间等。
实验二进程调度⒈实验内容进程调度模拟实验。
⒉实验目的通过模拟进程调度算法,了解进程调度的过程并比较不同的调度算法的区别。
⒊实验题目设计一段程序来模拟优先级调度算法和时间片轮转算法。
要求可以指定进程的数量、各进程需要CPU的时间和各进程的优先级。
⒋实验提示⑴进程调度算法是指处理机的分配策略。
优先数调度算法是指对每个进程确定一个优先数,进程调度总是让具有最高优先数的进程先使用处理机。
如果进程具有相同的优先数,再按先来先服务的次序分配处理机。
在本实例中采用动态优先数算法。
时间片轮转算法是指就绪进程按就绪的先后次序排成队列,每次总是选择就绪队列中的第一个进程占用处理机,但规定只能使用一个“时间片”。
⑵系统中的进程可以用进程控制块PCB来表示,PCB的结构定义如表5-8所示:表5-8 PCB结构⑶在进程调度时进程会交替的出现在运行、就绪和完成三种状态。
可以定义三个链表来存放三种状态的进程。
当进程运行时就把进程放入到运行链表中;当进程处于就绪状态时就将进程放入到就绪链表中;当进程运行完毕时就将进程放入到完成链表中。
由于同一时刻运行的进程只能有一个,所以运行链表只能有一个结点。
在实例程序中为了使程序更简洁忽略了进程的等待状态,仅运行了优先数调度算法,由于篇幅有限,仅显示部分结果,对于时间片轮转调度算法,请读者自行运行。
⑷主要变量及函数说明如表5-9所示:表5-9 主要变量及函数说明⒌实例代码//进程调度算法proc.c//运行环境Redhad9.0 gcc 4.0#include <stdio.h>#include <string.h>typedef struct pcb //定义PCB结构{char name[20]; /*进程标识符*/int cputime; /*进程占用CPU时间*/int prio; /*进程优先数*/int needtime; /*进程到完成还需要的CPU时间*/struct pcb *next;/*链指针*/}PCB;PCB *RUN,*READY,*RTAIL,*FINSH,*FTAIL;void PRINTLINK(int t)/*输出3个队列*/{PCB *p;printf("CPU运行次数:___%d___\n",t);printf("______________________\n");printf("进程名\t运行状态\t运行次数\t还需要运行次数\n");if(RUN!=NULL){printf("%s\t运行\t%d\t%d\n",RUN->name,RUN->cputime,RUN->needtime);}elseprintf("*运行状态为空\n");p=READY;if(p!=NULL){while(p!=NULL){printf("%s\t就绪\t%d\t%d\n",p->name,p->cputime,p->needtime);p=p->next;}}elseprintf("*就绪队列为空\n");p=FINSH;if (p!=NULL){while(p!=NULL){//printf(" 进程名字为:%s\n",p->name);printf("%s\t完成\t%d\t%d\n",p->name,p->cputime,p->needtime);p=p->next;}}elseprintf("*完成队列为空\n");getchar();}PCB *CPCBLINK()/*建立就绪队列*/{printf("建立就绪队列\n\n");int i,n,nt,pr;PCB *p,*q,*head;n=0;while(1){printf("请输入进程的个数(有效范围1-100):");scanf("%d",&n);printf("\n");if (n>=1&&n<=100)break;elseprintf("输入有误。
操作系统实验之处理机调度实验报告一、实验目的处理机调度是操作系统中的核心功能之一,本次实验的主要目的是通过模拟不同的处理机调度算法,深入理解操作系统对处理机资源的分配和管理策略,比较不同调度算法的性能差异,并观察它们在不同负载情况下的表现。
二、实验环境本次实验使用的操作系统为 Windows 10,编程语言为 Python 38。
实验中使用了 Python 的相关库,如`numpy`、`matplotlib`等,用于数据生成、计算和图形绘制。
三、实验原理1、先来先服务(FCFS)调度算法先来先服务算法按照作业到达的先后顺序进行调度。
先到达的作业先被服务,直到完成或阻塞,然后再处理下一个到达的作业。
2、短作业优先(SJF)调度算法短作业优先算法选择预计运行时间最短的作业先执行。
这种算法可以有效地减少作业的平均等待时间,但可能导致长作业长时间等待。
3、时间片轮转(RR)调度算法时间片轮转算法将处理机的时间分成固定长度的时间片,每个作业轮流获得一个时间片的处理时间。
当时间片用完后,如果作业还未完成,则将其放入就绪队列的末尾等待下一轮调度。
4、优先级调度算法优先级调度算法为每个作业分配一个优先级,优先级高的作业先被执行。
优先级可以根据作业的性质、紧急程度等因素来确定。
四、实验内容与步骤1、数据生成首先,生成一组模拟的作业,包括作业的到达时间、预计运行时间和优先级等信息。
为了使实验结果更具代表性,生成了不同规模和特征的作业集合。
2、算法实现分别实现了先来先服务、短作业优先、时间片轮转和优先级调度这四种算法。
在实现过程中,严格按照算法的定义和规则进行处理机的分配和调度。
3、性能评估指标定义了以下性能评估指标来比较不同调度算法的效果:平均等待时间:作业在就绪队列中的等待时间的平均值。
平均周转时间:作业从到达系统到完成的时间间隔的平均值。
系统吞吐量:单位时间内完成的作业数量。
4、实验结果分析对每种调度算法进行多次实验,使用不同的作业集合,并记录相应的性能指标数据。
计算机操作系统实验报告实验二进程调度算法一、实验名称:进程调度算法二、实验内容:编程实现如下算法:1.先来先服务算法;2.短进程优先算法;3.时间片轮转调度算法。
三、问题分析与设计:1.先来先服务调度算法先来先服务调度算法是一种最简单的调度算法,该算法既可以用于作业调度,也可用于进程调度。
当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将他们调入内存,为它们分配资源、创建进程,然后放入就绪队列。
在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。
该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。
FCFS算法比较有利于长作业(进程),2.短作业(进程)优先调度算法短作业(进程)优先调度算法SJ(P)F,是指对短作业或短进程优先调度的算法。
它们可以分别用于作业调度和进程调度。
短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。
而短进程(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机再重新调度。
SJ(P)F调度算法能有效地降低作业(进程)的平均等待时间,提高系统吞吐量。
该算法对长作业不利,完全未考虑作业的紧迫程度。
3.时间片轮转算法在时间片轮转算法中,系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。
当执行的时间片用完时,由一个计数器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。
这样就可以保证就绪队列中的所有进程在一给定的时间内均能获得一时间片的处理机执行时间。
换言之,系统能在给定的时间内响应所有用户的请求。
第1篇一、实验目的通过本次实验,加深对操作系统进程调度原理的理解,掌握先来先服务(FCFS)、时间片轮转(RR)和动态优先级(DP)三种常见调度算法的实现,并能够分析这些算法的优缺点,提高程序设计能力。
二、实验环境- 编程语言:C语言- 操作系统:Linux- 编译器:GCC三、实验内容本实验主要实现以下内容:1. 定义进程控制块(PCB)结构体,包含进程名、到达时间、服务时间、优先级、状态等信息。
2. 实现三种调度算法:FCFS、RR和DP。
3. 创建一个进程队列,用于存储所有进程。
4. 实现调度函数,根据所选算法选择下一个执行的进程。
5. 模拟进程执行过程,打印进程执行状态和就绪队列。
四、实验步骤1. 定义PCB结构体:```ctypedef struct PCB {char processName[10];int arrivalTime;int serviceTime;int priority;int usedTime;int state; // 0: 等待,1: 运行,2: 完成} PCB;```2. 创建进程队列:```cPCB processes[MAX_PROCESSES]; // 假设最多有MAX_PROCESSES个进程int processCount = 0; // 实际进程数量```3. 实现三种调度算法:(1)FCFS调度算法:```cvoid fcfsScheduling() {int i, j;for (i = 0; i < processCount; i++) {processes[i].state = 1; // 设置为运行状态printf("正在运行进程:%s\n", processes[i].processName); processes[i].usedTime++;if (processes[i].usedTime == processes[i].serviceTime) { processes[i].state = 2; // 设置为完成状态printf("进程:%s 完成\n", processes[i].processName); }for (j = i + 1; j < processCount; j++) {processes[j].arrivalTime--;}}}```(2)RR调度算法:```cvoid rrScheduling() {int i, j, quantum = 1; // 时间片for (i = 0; i < processCount; i++) {processes[i].state = 1; // 设置为运行状态printf("正在运行进程:%s\n", processes[i].processName); processes[i].usedTime++;processes[i].serviceTime--;if (processes[i].serviceTime <= 0) {processes[i].state = 2; // 设置为完成状态printf("进程:%s 完成\n", processes[i].processName); } else {processes[i].arrivalTime++;}for (j = i + 1; j < processCount; j++) {processes[j].arrivalTime--;}}}```(3)DP调度算法:```cvoid dpScheduling() {int i, j, minPriority = MAX_PRIORITY;int minIndex = -1;for (i = 0; i < processCount; i++) {if (processes[i].arrivalTime <= 0 && processes[i].priority < minPriority) {minPriority = processes[i].priority;minIndex = i;}}if (minIndex != -1) {processes[minIndex].state = 1; // 设置为运行状态printf("正在运行进程:%s\n", processes[minIndex].processName);processes[minIndex].usedTime++;processes[minIndex].priority--;processes[minIndex].serviceTime--;if (processes[minIndex].serviceTime <= 0) {processes[minIndex].state = 2; // 设置为完成状态printf("进程:%s 完成\n", processes[minIndex].processName); }}}```4. 模拟进程执行过程:```cvoid simulateProcess() {printf("请选择调度算法(1:FCFS,2:RR,3:DP):");int choice;scanf("%d", &choice);switch (choice) {case 1:fcfsScheduling();break;case 2:rrScheduling();break;case 3:dpScheduling();break;default:printf("无效的调度算法选择。
#include <stdio.h>#include <stdlib.h>#include <windows.h>typedef struct node{int name; //进程标识符int cputime; //进程占用CPU时间int needtime; //进程到完成还要的时间int totaltime;//进程需要的总时间int count; //计数器struct node *next; //链指针}PCB;PCB *finish,*finishtail,*ready,*readytail,*run,*block,*blocktail; //队列指针int time;#define N 5#define TIME 4//初始化就绪状态队列void InitReady(){ready=NULL;readytail=NULL;}//初始化运行状态进程指针void InitRun(){run=NULL;}//初始化阻塞队列void InitBlock(){block=NULL;blocktail=NULL;}//初始化已完成队列void InitEixt(){finish=NULL;finishtail=NULL;}//就绪队列入队void PushReady(PCB *p1){p1->count=0;p1->cputime=0;if(ready==NULL){p1->next=ready;ready=p1;readytail=p1;}else{readytail->next=p1;readytail=p1;p1->next=NULL;}}//已完成进程入队void PushExit(PCB *exit) {if(finish==NULL){exit->next=finish;finish=exit;finishtail=exit;}else{finishtail->next=exit;finishtail=exit;exit->next=NULL;}}//就绪队列出队void PopReady(){if(ready!=NULL)run=ready; //就绪队列头指针赋值给运行头指针else{printf("就绪队列为空,不能出队\n");printf(" \n");}ready=ready->next;}//创建进程int Create(){PCB *p;int i=1,myname;printf("请输入进程号和需要的总时间片,最多输入10个进程,输入-1结束输入\n");scanf("%d",&myname);scanf("%d",&time);while (i<=N&&myname!=-1&&time!=-1&&time<=TIME){p=(PCB *)malloc(sizeof(PCB));p->name=myname;p->cputime=0;p->needtime=time;p->count=0; //计数器p->totaltime=time;PushReady(p);printf("此次创建进程的进程号:%d\n",p->name);printf("此次创建进程的所需运行时间:%d\n",p->totaltime);printf("请继续如有需要请继续创建\n");scanf("%d",&myname);scanf("%d",&time);i++;}if(i>N)printf(" 输入进程数已达最大数\n");if (time>TIME){printf("输入的时间片超过最大时间片\n");printf("结束该模拟模式\n");exit(1);}if(myname!=-1||time!=-1){printf(" 进程创建完毕\n");}return 1;}//阻塞队列入队void PushBlock(PCB *coming){if(block==NULL){coming->next=block;block=coming;blocktail=coming;}else{blocktail->next=coming;blocktail=coming;coming->next=NULL;}}//阻塞队列出队int PopBlock(){PCB *take,*pre,*blocking;int temp;if(block==NULL){printf("阻塞队列为空,不能出队。
操作系统实验报告(二)实验题目:进程调度算法实验环境:C++实验目的:编程模拟实现几种常见的进程调度算法,通过对几组进程分别使用不同的调度算法,计算进程的平均周转时间和平均带权周转时间,比较各种算法的性能优劣。
实验内容:编程实现如下算法:1.先来先服务算法;2.短进程优先算法;3.时间片轮转调度算法。
设计分析:程序流程图:1.先来先服务算法2.短进程优先算法3.时间片轮转调度算法实验代码:1.先来先服务算法#include <iostream.h>#define n 20typedef struct{int id; //进程名int atime; //进程到达时间int runtime; //进程运行时间}fcs;void main(){int amount,i,j,diao,huan;fcs f[n];cout<<"请输入进程个数:"<<endl;cin>>amount;for(i=0;i<amount;i++){cout<<"请输入进程名,进程到达时间,进程运行时间:"<<endl; cin>>f[i].id;cin>>f[i].atime;cin>>f[i].runtime;}for(i=0;i<amount;i++) //按进程到达时间的先后排序{ //如果两个进程同时到达,按在屏幕先输入的先运行for(j=0;j<amount-i-1;j++){ if(f[j].atime>f[j+1].atime){diao=f[j].atime;f[j].atime=f[j+1].atime;f[j+1].atime=diao;huan=f[j].id;f[j].id=f[j+1].id;f[j+1].id=huan;}}}for(i=0;i<amount;i++){cout<<"进程:"<<f[i].id<<"从"<<f[i].atime<<"开始"<<","<<"在"<<f[i].atime+f[i].runtime<<"之前结束。
院系:计算机学院实验课程:操作系统实验项目:进程调度的设计与实现指导老师:陈红英老师开课时间:2011 ~ 2012年度第 2学期专业:网络工程班级:10级学生:yuth学号:*一、实验项目名称进程调度的设计与实现二、实验目的及要求1、综合应用下列知识点设计并实现操作系统的进程调度:邻接表,布尔数组,非阻塞输入,图形用户界面GUI,进程控制块,进程状态转换,多级反馈队列进程调度算法。
2、加深理解操作系统进程调度的过程。
3、加深理解多级反馈队列进程调度算法。
三、实验主要硬件软件环境32位PC机,VC++6四、实验内容及步骤1、采用一种熟悉的语言,如C、PASCAL 或C++等,编制程序,最好关键代码采用C/C++,界面设计可采用其它自己喜欢的语言。
2、采用多级反馈队列调度算法进行进程调度。
3、每个进程对应一个PCB 。
在PCB 中包括进程标识符pid、进程的状态标识status、进程优先级priority、进程的队列指针next 和表示进程生命周期的数据life(在实际系统中不包括该项)。
4、创建进程时即创建一个PCB,各个进程的pid 都是唯一的,pid 是在1 到100 范围内的一个整数。
可以创建一个下标为 1 到100 的布尔数组,“真”表示下标对应的进程标识号是空闲的,“假”表示下标对应的进程标识号已分配给某个进程。
5、进程状态status 的取值为“就绪ready ”或“运行run ”,刚创建时,状态为“ready ”。
被进程调度程序选中后变为“run ”。
6、进程优先级priority 是0 到49 范围内的一个随机整数。
7、进程生命周期life 是1 到5 范围内的一个随机整数。
8、初始化时,创建一个邻接表,包含50 个就绪队列,各就绪队列的进程优先级priority 分别是0 到49 。
9、为了模拟用户动态提交任务的过程,要求动态创建进程。
进入进程调度循环后,每次按ctrl+f 即动态创建一个进程,然后将该PCB 插入就绪队列中。
一、实验目的1. 理解单进程调度算法的基本原理。
2. 掌握单进程调度算法的设计与实现。
3. 分析不同单进程调度算法的性能。
二、实验内容本次实验主要设计了以下三种单进程调度算法:先来先服务(FCFS)、最短作业优先(SJF)和最短剩余时间优先(SRTF)。
1. 先来先服务(FCFS)算法FCFS算法是一种最简单的调度算法,按照进程到达的顺序进行调度。
具体实现步骤如下:(1)创建一个进程队列,用于存储所有就绪进程。
(2)将到达的进程依次加入队列。
(3)从队列中取出第一个进程,分配CPU执行。
(4)执行完成后,将该进程从队列中移除。
2. 最短作业优先(SJF)算法SJF算法根据进程需要的执行时间来调度进程,优先选择执行时间最短的进程。
具体实现步骤如下:(1)创建一个进程队列,用于存储所有就绪进程。
(2)遍历队列,找出执行时间最短的进程。
(3)将选出的进程分配CPU执行。
(4)执行完成后,将该进程从队列中移除。
3. 最短剩余时间优先(SRTF)算法SRTF算法是对SJF算法的改进,它考虑了进程的动态变化。
具体实现步骤如下:(1)创建一个进程队列,用于存储所有就绪进程。
(2)遍历队列,找出剩余执行时间最短的进程。
(3)将选出的进程分配CPU执行。
(4)执行过程中,若队列中有其他进程的剩余执行时间更短,则将当前进程挂起,并将新进程分配CPU执行。
(5)执行完成后,将该进程从队列中移除。
三、实验过程1. 编写单进程调度算法的程序代码。
2. 对比三种算法的性能,包括平均周转时间、平均等待时间和平均带权周转时间。
3. 分析不同算法的优缺点。
四、实验结果与分析1. 实验结果(1)FCFS算法平均周转时间:20.0平均等待时间:10.0平均带权周转时间:1.0(2)SJF算法平均周转时间:15.0平均等待时间:7.5平均带权周转时间:0.75(3)SRTF算法平均周转时间:12.0平均等待时间:6.0平均带权周转时间:0.62. 实验分析(1)FCFS算法FCFS算法简单易实现,但会导致长作业饥饿现象,即长作业在系统中等待时间过长。
操作系统实验报告--进程调度计科02-8 王长青05年4月17日计算机操作系统实验——进程调度一.实验目的进程调度是处理机管理的核心内容。
通过本实验可以加深理解有关进程控制块、进程队列的概念,并体会和了解优先数调度算法的具体实施办法。
二.程序功能本程序使用VC++编译调试,用于实现进程优先数调度的模拟。
主要包含三个模块:1、主界面:用于显示进程调度的过程。
2、数据录入模块:用于获取进程的初始值,其中有三种获取方式,手动输入方式、随即生成方式和从文件中读去数据的方式。
当用户在主窗口中点击“开始”菜单项时即可打开数据录入对话框,用户通过这三种方式之一均可完成数据的录入。
3、进程控制模块:主要实现创建新的进程,就绪队列的管理,完成队列的管理,进程的调度。
三.实验原理(1)本程序采用优先数调度算法对进程进行调度,每个进程可有三个状态,即:就绪状态,运行状态,完成状态。
并假设初始状态为就绪状态。
这三种状态的转换情况如右图:(2)为了便于处理,程序中的某进程运行时间以时间片为单位计算。
各进程的优先数以及进程需运行的时间片数的初始值均由用户给定(通过数据录入模块完成)。
(3)程序通过设置一个定时器来实现时间片的轮转,时间片的大小是1秒,在定时器消息的响应函数中从用户录入的数据中读取一个创建进程,将其加入到就绪队列中,然后进行调度和执行。
在调度函数中,对于遇到优先数一致的情况,采用FIFO策略解决。
(4)在优先数算法中,进程每执行一次,优先数减3,进程还需要运行的时间数减1。
四.详细设计(1)设计进程控制块PCB结构:struct PCB{ int pid; //进程号int pri; //进程优先数int time; //进程所需运行时间int status; // 进程状态 0就绪,1 执行,-1完成};(2)将进程的各种操作封装在类CProMoni中,该类的定义如下:class CProMoni{public:CProMoni();virtual ~CProMoni();void InsertRQ(PCB* p); //将p所指的进程插入到就绪队列中void InsertFQ(PCB* p); //将p所指的进程插入到完成队列中void ProSchedule(); //进程调度函数void ProRun(); //运行函数void Display(CDC* pDC); //以表格形式输出运行过程bool GetFinishFlag();bool OpenLogFile(); //打开日志文件void CloseLogFile(); //关闭日志文件bool WriteLogToFile(); //向日志文件中写入数据private:PCB *m_pRunning; //指向当前运行的进程CPtrList m_readyList; //就绪队列CPtrList m_finishList; //完成队列bool m_finish; //完成标志CString m_LogFileName; //日志文件名CStdioFile m_LogFile; //日志文件public:int m_clock; //时钟序列};(3)主要成员函数的实现:void CProMoni::InsertRQ(PCB* p){ //将p插入到就绪队列中POSITION pre,pos=m_readyList.GetHeadPosition();PCB *q;while(pos!=NULL){pre=pos;q=(PCB*)m_readyList.GetNext(pos);if(q->pri < p->pri){m_readyList.InsertBefore(pre,p);return;}}if(pos==NULL){m_readyList.AddTail(p);}}void CProMoni::ProSchedule(){//进程调度PCB *p;if(m_pRunning==NULL){if(m_readyList.IsEmpty()){m_finish=true;return;}else{p=(PCB*)m_readyList.RemoveHead();m_pRunning=p;}}else{if(!m_readyList.IsEmpty()){p=(PCB*)m_readyList.GetHead();//m_readyList将头节点与当前PCB的权值比较if(p->pri > m_pRunning->pri ){PCB *q=m_pRunning;m_pRunning=(PCB*)m_readyList.RemoveHead();m_pRunning->status=1;q->status=0;InsertRQ(q);}}}}void CProMoni::ProRun(){//运行进程if(!m_finish){if(m_pRunning==NULL){ AfxMessageBox("当前运行的进程不存在!");return;}m_pRunning->pri-=3;m_pRunning->time-=1;{ m_pRunning->time=0;PCB*p=m_pRunning;p->status=-1;InsertFQ(p);m_pRunning=NULL;}}}(4)试图类的主要成员函数:PCB* CProcessView::CreatePCB(){//创建PCBPCB* p=new PCB;p->pid=n+1;p->pri=m_pris[n];p->time=m_times[n];p->status=0;n++;return p;}#include"pritimedlg.h"void CProcessView::OnStart(){ CPriTimeDlg dlg; //定义数据录入对话框dlg.DoModal();if(dlg.m_ok){ m_proTotal=dlg.m_proNum;for(int i=0;i<m_proTotal;i++){ m_pris[i]=dlg.m_pris[i];m_times[i]=dlg.m_times[i];}m_proMoni.OpenLogFile(); //打开日志文件PCB* p=CreatePCB(); //创建新进程m_proMoni.InsertRQ(p); //将新进程插入到就绪队列中m_proMoni.WriteLogToFile(); //写日志文件m_proMoni.ProSchedule(); //进程调度m_start=true; //设置开始标志Invalidate(); //刷新视图m_killTimer=false;SetTimer(1,1000,NULL);//设置定时器}}void CProcessView::OnTimer(UINT nIDEvent){ m_proMoni.m_clock++;m_proMoni.WriteLogToFile();//写日志m_proMoni.ProRun(); //运行进程if(n<m_proTotal){ PCB *p=CreatePCB();//创建新进程m_proMoni.InsertRQ(p);}m_proMoni.ProSchedule();Invalidate();if(m_proMoni.GetFinishFlag()){//若已完成则删除定时器KillTimer(1);m_killTimer=true;AfxMessageBox("演示完毕");}CScrollView::OnTimer(nIDEvent);}五.运行结果(1)数据录入界面:(2)进程调度过程的结果:六、实验总结通过本实验使我对进程的相关概念及进程的优先数调度算法有了更深的理解,使自己在程序设计及编制方面也有了一定的提高。
实验报告二——进程调度算法的设计姓名: xxxx 学号: xxxxx班级: xxxx一、实习内容•实现短进程优先调度算法(SPF)•实现时间片轮转调度算法(RR)二、实习目的•通过对进程调度算法的设计, 深入理解进程调度的原理。
进程是程序在一个数据集合上运行的过程, 它是系统进行资源分配和调度的一个独立单位。
进程调度分配处理机, 是控制协调进程对CPU的竞争, 即按一定的调度算法从就绪队列中选中一个进程, 把CPU的使用权交给被选中的进程。
三、实习题目• 1.先来先服务(FCFS)调度算法原理: 每次调度是从就绪队列中, 选择一个最先进入就绪队列的进程, 把处理器分配给该进程, 使之得到执行。
该进程一旦占有了处理器, 它就一直运行下去, 直到该进程完成或因发生事件而阻塞, 才退出处理器。
将用户作业和就绪进程按提交顺序或变为就绪状态的先后排成队列, 并按照先来先服务的方式进行调度处理, 是一种最普遍和最简单的方法。
它优先考虑在系统中等待时间最长的作业, 而不管要求运行时间的长短。
按照就绪进程进入就绪队列的先后次序进行调度, 简单易实现, 利于长进程, CPU繁忙型作业, 不利于短进程, 排队时间相对过长。
• 2.时间片轮转调度算法RR原理: 时间片轮转法主要用于进程调度。
采用此算法的系统, 其程序就绪队列往往按进程到达的时间来排序。
进程调度按一定时间片(q)轮番运行各个进程.进程按到达时间在就绪队列中排队, 调度程序每次把CPU分配给就绪队列首进程使用一个时间片, 运行完一个时间片释放CPU, 排到就绪队列末尾参加下一轮调度, CPU分配给就绪队列的首进程。
固定时间片轮转法:1 所有就绪进程按FCFS 规则排队。
2 处理机总是分配给就绪队列的队首进程。
3 如果运行的进程用完时间片, 则系统就把该进程送回就绪队列的队尾, 重新排队。
4 因等待某事件而阻塞的进程送到阻塞队列。
5 系统把被唤醒的进程送到就绪队列的队尾。
实验三进程调度一. 实验目的加深理解并模拟实现进程(作业)调度算法。
1)熟悉常用的进程调度算法, 如FCFS、SPF、FPF、高响应比优先、时间片轮转;2)结合所学的数据结构及编程知识, 选择三种进程调度算法予以实现。
二. 实验属性该实验为设计性实验。
三. 实验仪器设备及器材普通PC386以上微机四. 实验要求本实验要求2学时完成。
1)本实验要求完成如下任务:2)编程实现单处理机系统中的进程调度, 要求从FCFS、SPF、FPF、高响应比优先、时间片轮转算法中至少选择三个;3)最后编写主函数对所做工作进行测试。
实验前应复习实验中所涉及的理论知识和算法, 针对实验要求完成基本代码编写并完成预习报告、实验中认真调试所编代码并进行必要的测试、记录并分析实验结果。
实验后认真书写符合规范格式的实验报告(参见附录A), 并要求用正规的实验报告纸和封面装订整齐, 按时上交。
五: 实验具体设计此程序模拟了两种调度算法, FCFS和SPF, 首先FCFS就是按照进程的创建顺序依次顺序进行, 流程图为:进程顺序执行SPF:每次都进行循环, 选出在该时间刻运行时间最短的进程优先执行。
1.程序代码具体详解:2.创建一结构体作为进程控制器typedef struct PCB{int ID;char state;int arrivetime;int starttime;int finishtime;int servicetime;struct PCB *next;}pcb;定义全局变量作为计时器int time;//计时器创建进程链表:从txt文件中读取数据, 构造一条不含头结点的单链表void Create_process(){ifstream inFile;inFile.open("test.txt");inFile>>n;inFile.get();int i=0;for (;i<n;i++){p=(pcb *)malloc(sizeof(pcb));inFile>>p->ID;inFile>>p->arrivetime;inFile>>p->servicetime;p->starttime=0;p->finishtime=0;p->state='F';p->next=NULL;if(head==NULL){head=p;q=p;time=p->arrivetime;}if(p->arrivetime < time)time=p->arrivetime;q->next=p;q=p;}若执行FCFS算法, 按顺序遍历链表void fcfs1(){int i;p=head;for(i=0;i<n;i++){if(p->state=='F')q=p;run_fcfs1(q);}p=p->next;}}void run_fcfs1(pcb *p1){time = p1->arrivetime > time? p1->arrivetime:time;p1->starttime=time;printf("\n现在时间: %d,开始运行作业%d\n",time,p1->ID);time+=p1->servicetime;p1->state='T';p1->finishtime=time;printf("ID号到达时间开始运行时间服务时间完成时间\n");printf("%d%10d%12d%12d%12d\n",p1->ID,p1->arrivetime,p1->starttime,p1->servicetime,p 1->finishtime);}若执行SPF算法, 每次都从链表头开始遍历链表, 找出arrivetime<=time并且运行时间最短的节点, 执行该节点进程, 最后再删除该节点。
实验二、进程管理
一、实验目的
1.了解进程调度在操作系统中的作用;
2.模拟进程调度的实现。
二、实验环境与地点
1.实验环境
JDK1.5以上
2.实验地点:
软件工程系计算机实践基地
三、实验内容与步骤
要求:将输入数据按优先级进行排队,每次调度优先级最高的进程运行1个时间片,时间片到后,若还没运行完成,则重新插入队列等待调度。
模拟其调度过程。
结果输出:要求输出每次调度后正在运行的进程和等待队列中进程的情况(名称,状态,优先级等)。
四、实验总结与分析。
实验二、进程调度实验【实验目的及要求】用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。
要求选做实验内容中的一题。
【实验环境】编程环境:Visual C++操作系统软件:windows XP【预习要求】按照实验指导书要求事先编好程序;准备好需要输入的中间数据;估计可能出现的问题;预计可能得到的运行结果。
【实验内容】1、设计一个有N个进程共行的进程调度程序。
2、编写并调试一个模拟的进程调度程序,采用“最高优先数优先”调度算法对五个进程进行调度。
【算法描述及实验步骤】实验1算法描述:进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。
每个进程有一个进程控制块(PCB)表示。
进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。
进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。
进程的到达时间为进程输入的时间。
进程的运行时间以时间片为单位进行计算。
每个进程的状态可以是就绪W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
就绪进程获得CPU后都只能运行一个时间片。
用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
重复以上过程,直到所有进程都完成为止。
实验2算法描述:“最高优先数优先”调度算法的基本思想是把CPU分配给就绪队列中优先数最高的进程。
静态优先数是在创建进程时确定的,并在整个进程运行期间不再改变。
动态优先数是指进程的优先数在创建进程时可以给定一个初始值,并且可以按一定原则修改优先数。
实验二单处理器系统的进程调度(附实验报告)1.实验目的加深对进程概念的理解,明确进程和程序的区别;深入了解系统如何组织进程、创建进程;进一步认识如何实现处理器调度。
2.实验预备知识进程的概念;进程的组织方式;进程的创建;进程的调度。
3.实验内容编写程序完成单处理机系统中的进程调度,要求采用时间片轮转调度算法。
实验具体包括:首先确定进程控制块的内容,进程控制块的组成方式;然后完成进程创建原语和进程调度原语;最后编写主函数对所作工作进程测试。
4.提示与讲解这个实验主要要考虑三个问题:如何组织进程、如何创建进程和如何实现处理器调度。
考虑如何组织进程,首先就要设定进程控制块的内容。
进程控制块PCB 记录各个进程执行时的情况。
不同的操作系统,进程控制块记录的信息内容不一样。
操作系统功能越强,软件也越庞大,进程控制块记录的内容也就越多。
这里的实验只使用了必不可少的信息。
一般操作系统中,无论进程控制块中信息量多少,信息都可以大致分为以下四类:①标识信息每个进程都要有一个惟一的标识符,用来标识进程的存在和区别于其他进程。
这个标识符是必不可少的,可以用符号或编号实现,它必须是操作系统分配的。
在后面给出的参考程序中,采用编号方式,也就是为每个进程依次分配一个不相同的正整数。
②说明信息用于记录进程的基本情况,例如进程的状态、等待原因、进程程序存放位置、进程数据存放位置等等。
实验中,因为进程没有数据和程序,仅使用进程控制块模拟进程,所以这部分内容仅包括进程状态。
③现场信息现场信息记录各个寄存器的内容。
当进程由于某种原因让出处理器时,需要将现场信息记录在进程控制块中,当进行进程调度时,从选中进程的进程控制块中读取现场信息进行现场恢复。
现场信息就是处理器的相关寄存器内容,包括通用寄存器、程序计数器和程序状态字寄存器等。
在实验中,可选取几个寄存器作为代表。
用大写的全局变量AX、BX、CX、DX模拟通用寄存器、大写的全局变量PC模拟程序计数器、大写的全局变量PSW模拟程序状态字寄存器。
④管理信息管理信息记录进程管理和调度的信息。
例如进程优先数、进程队列指针等。
实验中,仅包括队列指针。
因此可将进程控制块结构定义如下:struct pcb{int name;int status;int ax, bx, cx,dx;int pc;int psw;int next;}确定进程控制块内容后,要考虑的就是如何将进程控制块组织在一起。
多道程序设计系统中,往往同时创建多个进程。
在单处理器的情况下,每次只能有一个进程处于运行态,其他的进程处于就绪状态或等待状态。
为了便于管理,通常把处于相同状态的进程的进程控制块链接在一起。
单处理器系统中,正在运行的进程只有一个。
因此,单处理器系统中进程控制块分成一个正在运行进程的进程控制块、就绪进程的进程控制块组织成的就绪队列和等待进程的进程控制块组成的等待队列。
由于实验模拟的是进程调度,没有对等待队列的操作,所以实验中只有一个指向正在运行进程的进程控制块指针和一个就绪进程的进程控制块队列指针。
操作系统的实现中,系统往往在主存中划分出一个连续的专门区域存放系统的进程控制块,实验中应该用数组模拟这个专门的进程控制块区域,定义如下:#define n 10struct pcb pcbarea[n];这样,进程控制块的链表实际上是数据结构中使用的静态链表。
进程控制块的链接方式可以采用单向和双向链表,实验中,进程控制块队列采用单向不循环静态链表。
为了管理空闲进程控制块,还应该将空闲控制块链接成一个队列。
实验中采用时间片轮转调度算法,这种算法是将进程控制块按照进入就绪队列的先后次序排成队列。
关于就绪队列的操作就是从队头摘下一个进程控制块和从队尾挂入一个进程控制块。
因此为就绪队列定义两个指针,一个头指针,指向就绪队列的第一个进程控制块;一个尾指针,指向就绪队列的最后一个进程控制块。
实验中指向运行进程的进程控制块指针、就绪队列指针和空闲进程控制块队列指针定义如下:int run;struct{int head;int tail;}ready;int pfree;以上是如何组织进程,下面考虑如何创建进程。
进程创建是一个原语,因此在实验中应该用一个函数实现,进程创建的过程应该包括:①申请进程控制块:进程控制块的数量是有限的,如果没有空闲进程控制块,则进程不能创建,如果申请成功才可以执行第②步;②申请资源:除了进程控制块外,还需要有必要的资源才能创建进程,如果申请资源不成功,则不能创建进程,并且归还已申请的进程控制块;如果申请成功,则执行第三步,实验无法申请资源,所以模拟程序忽略了申请资源这一步;③填写进程控制块:将该进程信息写入进程控制块内,实验中只有进程标识符、进程状态可以填写,每个进程现场信息中的寄存器内容由于没有具体数据而使用进程(模拟进程创建时,需输入进程标识符字,进程标识符本应系统建立,并且是惟一的,输入时注意不要冲突),刚刚创建的进程应该为就绪态,然后转去执行第四步;④挂入就绪队列:如果原来就绪队列不为空,则将该进程控制块挂入就绪队列尾部,并修改就绪队列尾部指针;如果原来就绪队列为空,则将就绪队列的头指针、尾指针均指向该进程控制块,进程创建完成。
进程创建流程图如图2.2所示。
多道程序设计的系统中,处于就绪态的进程往往是多个,它们都要求占用处理器,可是单处理器系统的处理器只有一个,进程调度就是解决这个处理器竞争问题的。
进程调度的任务就是按照某种算法从就绪进程队列中选择一个进程,让它占有处理器。
因此进程调度程序就应该包括两部分,一部分是在进程就绪队列中选择一个进程,并将其进程控制块从进程就绪队列中摘下来,另一部分工作就是分配处理器给选中的进程,也就是将指向正在运行进程的进程控制块指针指向该进程的进程控制块,并将该进程的进程控制块信息写入处理器的各个寄存器中。
图2.2进程创建流程图实验中采用时间片轮转调度算法。
时间片轮转调度算法让就绪进程按就绪的先后次序排成队列,每次总是选择就绪队列中的第一个进程占有处理器,但是规定只能使用一个“时间片”。
时间片就是规定进程一次使用处理器的最长时间。
实验中采用每个进程都使用相同的不变的时间片。
采用时间片轮转调度算法的进程调度流程图如图2.3所示。
完成上述功能后,编写主函数进行测试:首先建立一个就绪队列,手工输入信息建立几个进程;然后进行进程调度;最后将指向正在运行进程的指针指向的进程控制块的内容输出,察看结果。
图2.3进程调度流程图5.课外题编程实现采用优先数调度算法的进程调度。
我的实现代码(C语言):#include <stdio.h>#define N 10 //系统中所允许的最大进程数量#define SLOT 5 //时间片大小//进程状态枚举typedef enum{Running, //运行状态Aready, //就绪状态Blocking //阻塞状态} ProStatus;//进程控制块typedef struct{int name; //进程标识符ProStatus status; //进程状态int ax,bx,cx,dx; //通用寄存器int pc; //程序计数器寄存器int psw; //程序状态字寄存器int next; //指向下一个进程的指针} PCB;//就绪队列指针typedef struct{int head; //头指针int tail; //尾指针} Ready;//模拟寄存器int PSW,AX,BX,CX,DX,PC,TIME;//PCB的静态链表PCB pcbArea[N]; //模拟PCB区域的数组int run; //运行状态程序的指针Ready ready; //就绪队列指针int pfree; //空闲队列的指针//初始化运行状态进程指针void InitRun(){run=-1;}//初始化就绪状态队列void InitReady(){ready.head=ready.tail=-1;}//初始化空闲队列void InitFree(){int temp;for(temp=0;temp<N-1;temp++)pcbArea[temp].next=temp+1;}pcbArea[temp].next=-1;pfree=0;}//就绪队列出队int PopReady() //返回结点在PCB区域数组的编号{int temp;if(ready.head==-1){printf("就绪队列为空,不能出队。
\n");return -1;}temp=ready.head;ready.head=pcbArea[temp].next;if(ready.head==-1)ready.tail=-1;pcbArea[temp].next=-1;return temp;}//空闲队列出队int PopFree() //返回结点在PCB区域数组的编号{int temp;if(pfree==-1)printf("空闲队列为空,不能出队。
\n");return -1;}temp=pfree;pfree=pcbArea[temp].next;pcbArea[temp].next=-1;return temp;}//就绪队列入队void PushReady(int x) //x为入队结点的编号{int temp;if(ready.head==-1){ready.head=x;ready.tail=x;}else{temp=ready.tail;ready.tail=x;}pcbArea[ready.tail].next=-1;}//创建PCBvoid CreatePCB(int x,PCB pcb) //x为要创建PCB在PCB区域数组的编{pcbArea[x].ax=pcb.ax;pcbArea[x].bx=pcb.bx;pcbArea[x].cx=pcb.cx;pcbArea[x].dx=pcb.dx;pcbArea[x].name=;pcbArea[x].next=-1;pcbArea[x].pc=pcb.pc;pcbArea[x].psw=pcb.psw;pcbArea[x].status=pcb.status;}//创建进程函数void Create(PCB pcb){int temp;if(pfree==-1){printf("空闲队列为空,不能创建进程。
\n");return;}temp=PopFree();pcb.status=Aready;CreatePCB(temp,pcb);PushReady(temp);}//进程调度函数void Schedule()int temp;if(ready.head==-1){printf("系统内没有进程可以调度。