进程已获得除CPU之外的所有必须资源,只等待操作系统利用CPU调度算法将CPU分配给该进程以便执行。
创新互联建站网站建设服务商,为中小企业提供成都网站建设、网站设计服务,网站设计,网站托管运营等一站式综合服务型公司,专业打造企业形象网站,让您在众多竞争对手中脱颖而出创新互联建站。
进程等待某一特定事件的出现。如[I/O操作,在该过程中,进程依旧位于内存内,且占有CPU资源。
(1)静态优先数法:
一开始创建的时候就确定他的优先数,并在运行时保持不变。确定优先数时可以让外设的进程优先,或者操作时间长的优先....
(2)动态优先数法:
克服无法修改优先数的问题。CPU占用时间过长优先数下降,进程等待时间过长,优先数提高。
时间片太短切换开销太大不划算,太长又变成了FCFS。
引入多个就绪队列,在时间片轮转基础上改进
最高优先级队列运行一个时间片,次高两个,低优先级四个。当该进程用完所分配时间片仍未执行完时,需要调入下一级队列,下一级队列只有在上一级队列为空时才有机会执行。如果进程执行时有新进程进入上级优先级的队列,则会中断该进程并放入原队列的队尾然后执行新进程。
非抢占式的先来先服务(First Come First Severd, FCFS)算法了。
顾名思义,先来后到,每次从就绪队列选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行。
这似乎很公平,但是当一个长作业先运行了,那么后面的短作业等待的时间就会很长,不利于短作业。
最短作业优先(Shortest Job First, SJF)调度算法同样也是顾名思义,它会优先选择运行时间最短的进程来运行,这有助于提高系统的吞吐量。
这显然对长作业不利,很容易造成一种极端现象。
高响应比优先 (Highest Response Ratio Next, HRRN)调度算法主要是权衡了短作业和长作业。
每次进行进程调度时,先计算「响应比优先级」,然后把「响应比优先级」最高的进程投入运行,「响应比优先级」的计算公式:
最古老、最简单、最公平且使用最广的算法就是时间片轮转(Round Robin, RR)调度算法。
时间片的长度就是一个很关键的点:
如果时间片设得太短会导致过多的进程上下文切换,降低了 CPU 效率;如果设得太长又可能引起对短作业进程的响应时间变长。
静态优先级:创建进程时候,就已经确定了优先级了,然后整个运行时间优先级都不会变化;
动态优先级:根据进程的动态变化调整优先级,比如如果进程运行时间增加,则降低其优先级,如果进程等待时间(就绪队列的等待时间)增加,则升高其优先级,也就是随着时间的推移增加等待进程的优先级。
(1)非抢占式:当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程。
(2)抢占式:当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行。
但是依然有缺点,可能会导致低优先级的进程永远不会运行。
设置了多个队列,赋予每个队列不同的优先级,每个队列优先级从高到低,同时优先级越高时间片越短;
新的进程会被放入到第一级队列的末尾,按先来先服务的原则排队等待被调度,如果在第一级队列规定的时间片没运行完成,则将其转入到第二级队列的末尾,以此类推,直至完成;
当较高优先级的队列为空,才调度较低优先级的队列中的进程运行。如果进程运行时,有新进程进入较高优先级的队列,则停止当前运行的进程并将其移入到原队列末尾,接着让较高优先级的进程运行。
对于短作业可能可以在第一级队列很快被处理完。对于长作业,如果在第一级队列处理不完,可以移入下次队列等待被执行,虽然等待的时间变长了,但是运行时间也会更长了,所以该算法很好的兼顾了长短作业,同时有较好的响应时间。
每次选择淘汰的页面将是以后永不使用,或者在最长时间内不再被访问的页面,这样可以保证最低的缺页率。
最佳置换算法可以保证最低的缺页率,但是实际上,只有进程执行的过程中才能知道接下来会访问到的是哪个页面。操作系统无法提前预判页面的访问序列。因此,最佳置换算法是无法实现的。
算法思想:每次选择淘汰的页面是最早进入内存的页面。
该算法很简单,每次淘汰最在内存中待时间最久的各个,下面分别给出系统为进程分为配三个内存块和四个内存块的执行情况图。访问序列为3,2,1,0,3,2,4,3,2,1,0,4
算法思想:每次淘汰的页面是最近最久未使用的页面。
实现方法:赋予每个页面对应的页表项中,用访问字段记录该页面自上次被访问以来所经历的时间t。当需要淘汰一个页面时,选择现有页面中t最大的页面,即最近最久未使用。
最佳置换算法性能最好,但无法实现。先进先出置换算法实现简单,但是算法性能差。最近最久未使用置换算法性能好,是最接近OPT算法性能的,但是实现起来需要专门的硬件支持,算法开销大。时钟置换算法是一种性能和开销均平衡的算法。又称CLOCK算法,或最近未用算法(NRU,Not Recently Used)
简单CLOCK算法算法思想:为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列。当某个页被访问时,其访问位置1.当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出;如果是1,暂不换出,将访问位改为0,继续检查下一个页面,若第一轮扫描中所有的页面都是1,则将这些页面的访问位一次置为0后,再进行第二轮扫描(第二轮扫描中一定会有访问位为0的页面,因此简单的CLOCK算法选择一个淘汰页面最多会经过两轮扫描)。
除了考虑一个页面最近有没有被访问过之外,操作系统还需要考虑页面有没有被修改过。
改进型时钟置换算法的算法思想:在其他在条件相同时,应该优先淘汰没有被修改过的页面,从而来避免I/O操作。
就是优先级可以按需要变化,例如因条件在某一时刻变化,我们需要变更优先级以更及时响应某个条件,如异常、中断、或线程等。
本题中的系统是两道作业系统,因此每次只能有两个作业进入系统,作业调度采
用短作业优先算法,只有调度进入系统的进程方能参与进程调度;进程调度采用
基于优先数的抢占式调度算法,高优先级的进程可以抢占系统处理机。
本题的作业和进程的推进过程如下:
10:00 A作业到达,被作业调度程序调度进入系统,被进程调度程序调度开始运行
10:20 A作业运行20分钟,剩余20分钟,由于优先级低,被进程调度程序调度处于就绪状态
B作业到达,被作业调度程序调度进入系统,由于优先级高,被进程调度程序调度处于开始运行状态
10:30 A作业等待10分钟,剩余20分钟,继续等待
B作业运行10分钟,剩余20分钟,继续运行
C作业到达,等待被作业调度程序调度
10:50 A作业等待30分钟,剩余20分钟,由于优先级高,被进程调度程序调度处于开始运行状态
B作业运行30分钟,作业完成,结束运行
C作业等待20分钟,由于估计运行时间较长,仍未被调入系统中运行
D作业到达,被进程调度程序调度处于就绪状态
11:10 A作业运行40分钟,作业完成,结束运行
C作业等待30分钟,被作业调度程序调度进入系统,由于优先级高,被进程调度程序调度处于开始运行状态
D作业等待10分钟,由于优先级低,被进程调度程序调度处于就绪状态
12:00 C作业运行50分钟,作业完成,结束运行
D作业等待70分钟,被进程调度程序调度处于开始运行状态
12:20 D作业运行20分钟,作业完成,结束运行
各作业周转时间为:
作业A 70,作业B 30,作业C 90,作业D 90。
平均作业周转时间为70分钟。
参考1.网页链接
2.网页链接
略改动。
给你两个例子,第一个:
第二个:
#include "stdio.h"
#include STDLIB.H
#include CONIO.H
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0
struct pcb { /* 定义进程控制块PCB */
char name[10];
char state;
int super;
int ntime;
int rtime;
struct pcb* link;
}*ready=NULL,*p;
typedef struct pcb PCB;
sort() /* 建立对进程进行优先级排列函数*/
{
PCB *first, *second;
int insert=0;
if((ready==NULL)||((p-super)(ready-super))) /*优先级最大者,插入队首*/
{
p-link=ready;
ready=p;
}
else /* 进程比较优先级,插入适当的位置中*/
{
first=ready;
second=first-link;
while(second!=NULL)
{
if((p-super)(second-super)) /*若插入进程比当前进程优先数大,*/
{ /*插入到当前进程前面*/
p-link=second;
first-link=p;
second=NULL;
insert=1;
}
else /* 插入进程优先数最低,则插入到队尾*/
{
first=first-link;
second=second-link;
}
}
if(insert==0) first-link=p;
}
}
input() /* 建立进程控制块函数*/
{
int i,num;
//clrscr(); /*清屏*/
printf("\n 请输入进程号?");
scanf("%d",num);
for(i=0;iNUM;I++) scanf(?%s?,p- 输入进程名:?); printf(?\n p="getpch(PCB);" 进程号No.%d:\n?,i); {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;
while(pr!=NULL)
{
l++;
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;
printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/
while(pr!=NULL)
{
disp(pr);
pr=pr-link;
}
}
destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/
{
printf("\n 进程 [%s] 已完成.\n",p-name);
free(p);
}
running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/
{
(p-rtime)++;
if(p-rtime==p-ntime)
destroy(); /* 调用destroy函数*/
else
{
(p-super)--;
p-state='w';
sort(); /*调用sort函数*/
}
}
main() /*主函数*/
{
int len, h=0;
char ch;
input();
len=space();
while((len!=0)(ready!=NULL))
{
ch=getchar();
h++;
printf("\n The execute number:%d \n",h);
p=ready;
ready=p-link;
p-link=NULL;
p-state='R';
check();
running();
printf("\n 按任一键继续......");
ch=getchar();
}
printf("\n\n 进程已经完成.\n");
ch=getchar();
}