实现操作系统的主要进程调度算法:先来先服务(FCFS)算法,短进程优先(SPN)算法和时间片轮转(RR)算法。
(1)先来先服务调度算法(FCFS)
该算法采用非剥夺策略,算法按照进程提交或进程变为就绪状态的先后次序,分派 CPU。当前进程占用CPU,直到执行完或阻塞,才出让CPU(非抢占方式)。在进程唤醒后(如I/O 完成),并不立即恢复执行,通常等到当前进程出让CPU。这是最简单的调度算法,比较有利于长进程,而不利于短进程,有利于CPU 繁忙的进程,而不利于I/O 繁忙的进程。
【算法与数据结构|进程调度--FCFS,SPN,RR算法的实现】(2)短进程优先调度算法(SPN)
该算法也采用非剥夺策略,对预计执行时间短的进程优先分派处理机。通常后来的短进程不抢先正在执行的进程。相比FCFS 算法,该算法可改善平均周转时间和平均带权周转时间,缩短进程的等待时间,提高系统的吞吐量。缺点是对长进程非常不利,可能长时间得不到执行,且未能依据进程的紧迫程度来划分执行的优先级,以及难以准确估计进程的执行时间,从而影响调度性能。
(3)时间片轮转算法(RR)
该算法采用剥夺策略。让就绪进程以FCFS 的方式按时间片轮流使用CPU 的调度方式,即将系统中所有的就绪进程按照FCFS 原则,排成一个队列,每次调度时将CPU 分派给队首进程,让其执行一个时间片,时间片的长度从几个ms 到几百ms。在一个时间片结束时,发生时钟中断,调度程序据此暂停当前进程的执行,将其送到就绪队列的末尾,并通过上下文切换执行当前的队首进程,进程可以未使用完一个时间片,就出让CPU(如阻塞)。时间片轮转调度算法的特点是简单易行、平均响应时间短,但不利于处理紧急作业。在时间片轮转算法中,时间片的大小对系统性能的影响很大,因此时间片的大小应选择恰当。
使用C语言实现FCFS,SPN,RR算法:
#include
#include//先来先服务,最短作业优先算法结构体
typedef struct process_FCFS
{
char name;
//进程名
float arrivetime;
//到达时间
float servetime;
//服务时间
float finishtime;
//完成时间
float roundtime;
//周转时间
float daiquantime;
//带权周转时间
struct process_FCFS *link;
//结构体指针}FCFS;
//时间片轮转算法结构体
typedef struct stud
{
char name;
//进程名
float arrive;
//进程到达时间
float run;
//进程运行时间
float rest;
//运行进程剩余时间
char *state;
//进程状态
struct stud *next;
//结构体指针
}stud;
FCFS *p,*q,*head=NULL;
struct process_FCFS a[100];
float avrRoundtime;
//平均周转时间
float avrDaiquantime;
//平均带权周转时间FCFS initial(struct process_FCFS a[],int n);
void print(struct process_FCFS a[],int n);
void Fcfs(struct process_FCFS a[],int n);
//FCFS算法
void SPN(struct process_FCFS a[],int n);
//SPN算法
struct process_FCFS *sortarrivetime(struct process_FCFS a[],int n);
//到达时间冒泡排序
struct process_FCFS *sortservetime(struct process_FCFS a[],int n);
//服务时间冒泡排序struct stud *create(int &a);
//初始化创建时间片轮转算法调度队列
void RR(struct stud *head, int &a);
//时间片轮转RR算法//按到达时间进行冒泡排序
struct process_FCFS *sortarrivetime(struct process_FCFS a[],int n)
{
int i,j;
struct process_FCFS t;
int flag;
for(i=1;
ia[j+1].arrivetime) //将到达时间短的交换到前边
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
flag=1;
//交换
}
}
if(flag==0)//如果一趟排序中没发生任何交换,则排序结束
{
break;
}
}
return a;
//返回排序后进程数组
}//按服务时间进行冒泡排序
struct process_FCFS *sortservetime(struct process_FCFS a[],int n)
{
int i,j;
struct process_FCFS t;
int flag;
for(i=1;
ia[j+1].servetime) //将到达时间短的交换到前边
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
flag=1;
//交换
}
}
if(flag==0)//如果一趟排序中没发生任何交换,则排序结束
{
break;
}
}
return a;
//返回排序后进程数组
}//先来先服务算法
void Fcfs(struct process_FCFS a[],int n,float &t1, float &t2)
{
int i;
a[0].finishtime=a[0].arrivetime+a[0].servetime;
//完成时间=到达时间-服务时间
a[0].roundtime=a[0].finishtime-a[0].arrivetime;
//周转时间=完成时间-提交时间
a[0].daiquantime=a[0].roundtime/a[0].servetime;
//带权时间=周转时间/服务时间
for(i=1;
iarrive);
printf("服务时间:");
scanf("%f",&p->run);
p->rest = p->run;
p->state = "ready";
if(rear == NULL)
{
head = p;
p->next = NULL;
rear = p;
}
else
{
t = NULL;
q = head;
while(q && q->arrive < p->arrive)
{
t = q;
q = q->next;
}if(q == head)
{
p->next = head;
head = p;
}
else if(t == rear)
{
rear->next = p;
p->next = NULL;
rear = p;
}
else
{
t->next = p;
p->next = q;
}
} }
return head;
}//时间片轮转算法
void RR(struct stud *head, int &a)
{
struct stud *p,*t,*r;
float slice = 0.0f;
float temp = 0.0f;
//缓存最后一个正数rest
float m1 = 0.0f , m2 = 0.0f, n1 = 0.0f, n2 = 0.0f;
float sum_zhouzhuan = 0.0f, sum_daiquan = 0.0f;
//所有进程总周转时间,所有进程总带权周转时间
float zhouzhuan = 0.0f, daiquan = 0.0f;
//周转时间,带权周转时间
float avr_zhouzhuan = 0.0f, avr_daiquan = 0.0f;
printf("请输入时间块大小: ");
scanf("%f",&slice);
while(head != NULL) //队列非空,循环
{
r = p = head;
while(p != NULL) //遍历队列,结束后跳出当前循环
{
t = head;
m1 += slice;
temp = p->rest;
p->rest = p->rest - slice;
//剩余时间p->state = "running";
if(p->rest <= 0)
{
m1 = m1 - slice + temp;
//进程完成时间
zhouzhuan = m1 - p->arrive;
//进程周转时间
daiquan = zhouzhuan / (p->run);
//进程带权周转时间
sum_zhouzhuan += zhouzhuan;
//所有进程周转时间之和
sum_daiquan += daiquan;
p->rest = 0;
}
printf("\n-----------------------------------------------\n");
printf("name\tarrive\trun\trest\tstate\n");
while(t != NULL)
{
printf("%d\t%f\t%f\t%f\t%s\n",t->name,t->arrive,t->run,t->rest,t->state);
t = t->next;
}
if(p->rest == 0)/*判断是否删除结点*/
{ //finishtime +=
if(p == head)/*删除头结点*/
{
head = p->next;
free(p);
p = head;
}
else
{
r->next = p->next;
p = r->next;
r = p;
}
}
else
{
r = p;
p->state = "ready";
p = p->next;
}
}
}
printf("\n总周转时间: ");
printf("%f", sum_zhouzhuan);
printf("\n总带权周转时间: ");
printf("%f\n", sum_daiquan);
avr_zhouzhuan = sum_zhouzhuan / a;
avr_daiquan = sum_daiquan / a;
printf("\n平均周转时间: ");
printf("%f",avr_zhouzhuan);
printf("\n平均带权周转时间: ");
printf("%f\n",avr_daiquan);
}//主函数
void main()
{
float t1 = 0.0f;
//总周转时间
float t2 = 0.0f;
//总带权周转时间
float avr_t1 = 0.0f;
//平均周转时间
float avr_t2 = 0.0f;
//平均带权周转时间 int n,i;
char select = ' ';
//选择算法变量标识
while (select != 'e' && select != 'E') //不为退出标识,保持循环
{
printf("请选择算法:\na.先来先服务算法\nb.短作业优先算法\nc.时间片轮转算法\ne.退出程序\n输入选择字符标号:");
scanf("%c",&select);
if (select == 'a' || select == 'A') //先来先服务算法
{
printf("\n\n=================先来先服务算法================\n\n");
printf("请输入进程数:");
scanf("%d",&n);
for(i=0;
i
推荐阅读
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- C/C++|C/C++ basis 02
- Qt实战|Qt+OpenCV联合开发(二十一)--图像翻转与旋转
- Qt实战|Qt+OpenCV联合开发(十四)--图像感兴趣区域(ROI)的提取
- Qt实战|Qt+OpenCV联合开发(十三)--通道分离与合并
- opencv|Qt+OpenCV联合开发(十六)--图像几何形状绘制
- Qt实战|Qt+OpenCV联合开发(十七)--随机数与随机颜色
- SNAT的MASQUERADE地址选择与端口选择
- IPTABLES的连接跟踪与NAT分析
- IPVS分析