Bootstrap

进程调度算法的模拟实现

【实验目的】

1.理解和掌握课堂上讲的进程调度算法,并编程模拟实现调度过程。
2.研究进程调度算法的实现方法,并对算法性能参数进行对比。

【实验要求】

编程模拟实现传统的进程调度算法:FCFS调度算法、SPF调度算法、RR调度算法、优先级调度,高响应比优先等算法。

/*FCFS 和 SPF 调度算法*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
/*进程控制块*/
typedef struct{
	char pname;//进程名
	int arrive_t;//到达时间
	int service_t;//服务时间
	int finish_t;//完成时间
	int turnaround_t;//周转时间
	double w_turnaround_t;//带权周转时间
}PCB;

PCB p[20]; //声明n个进程控制块
int n=5;
/*初始化进程信息:进程名、到达时间、服务时间、状态*/
void init();
/*输出初状态*/
void original_P();
//排序
bool cmp1(PCB a,PCB b);
bool cmp2(PCB a,PCB b);
bool cmp3(PCB a,PCB b);
bool cmp4(PCB a,PCB b);
/*FCFS算法*/
void FCFS_work();
/*SPF算法*/
void SPF_work();
/*输出最终状态*/
void Print();
int main()
{
	init();
	original_P();
	char op;
	printf("请输入要使用的调度算法(<f/F-->FCFS> <s/S-->SPF>):");
	scanf("%c",&op);
	getchar();
	if(op=='s'||op=='S')
	{
		SPF_work();
	}
	if(op=='f'||op=='F')
	{
		FCFS_work();
	}
	Print();
	return 0;
}

void init()//初始化进程信息:进程名、到达时间、服务时间
{
	p[0].pname = 'A';
	p[0].arrive_t = 0;
	p[0].service_t = 3;
	
	p[1].pname = 'B';
	p[1].arrive_t = 2;
	p[1].service_t = 6;
	
	p[2].pname = 'C';
	p[2].arrive_t = 4;
	p[2].service_t = 4;
	
	p[3].pname = 'D';
	p[3].arrive_t = 6;
	p[3].service_t = 5;
	
	p[4].pname = 'E';
	p[4].arrive_t = 8;
	p[4].service_t = 2;
}
void original_P()//输出初始状态
{
	printf("进程初始状态\n");
	printf("------------------------------------------------------------------\n");
	printf("进程名\t\t到达时间\t服务时间\n");
	int i;
	for(i=0;i<n;i++)
	{
		printf("%c\t\t    %d\t\t    %d\n",p[i].pname,p[i].arrive_t,p[i].service_t);
	}
	printf("--------------------------------------------------------------------------------------------------\n");
 }
 bool cmp1(PCB a,PCB b)
{
    return a.arrive_t<b.arrive_t;//按到达时间从小到达排序
}
 void FCFS_work()
{
    sort(p,p+n,cmp1);
    p[0].finish_t=p[0].arrive_t+p[0].service_t;//第一个进程的完成时间=到达时间+服务时间
    for(int i=1;i<n;i++)
    {
        p[i].finish_t=max(p[i].arrive_t,p[i-1].finish_t)+p[i].service_t;//完成时间=开始运行时间+服务时间
    }

}

 //按先达到时间排序,再按服务时间排序
 bool cmp2(PCB a,PCB b)
 {
     if(a.arrive_t==b.arrive_t)
     {
         return a.service_t<b.service_t;
     }
     else
     {
         return a.arrive_t<b.arrive_t;
     }
 }
 //按服务时间排序
 bool cmp3(PCB a,PCB b)
 {
     return a.service_t<b.service_t;
 }
void SPF_work()
{
    sort(p,p+n,cmp2);//先按到达时间排序,再按进程服务时间排序
    p[0].finish_t=p[0].arrive_t+p[0].service_t;//第一个进程的完成时间=到达时间+服务时间
    int cnt=1;//判断完成时间内到达的进程个数,设第一个进程已经到达
    for(int i=1;i<n;i++)//看每一个进程 
    {
        if(cnt<n)
        {
             for(int j=i;j<n;j++)//看后面来的进程 
            {
                if(p[j].arrive_t<=p[i-1].finish_t)//比较到达时间和上一个进程的完成时间 
                {
                    cnt++;//如果已经达到就标记 
                }
                else
                    break;
            }
            if(cnt>i)//需要排序时 
                sort(p+i,p+cnt,cmp3);//按服务时间排序
        }
        p[i].finish_t=max(p[i-1].finish_t,p[i].arrive_t)+p[i].service_t;//完成时间 
    }
}
bool cmp4(PCB a,PCB b)
{
	return a.pname<b.pname;//按进程名排序 
}
void Print()
{
	printf("--------------------------------------------------------------------------------------------------\n");
	int i;
	printf("进程执行顺序为:\n");
	for(i=0;i<n;i++)
    {
        printf("%c ",p[i].pname);
    }
    printf("\n");
    sort(p,p+n,cmp4);
	printf("--------------------------------------------------------------------------------------------------\n");
	printf("进程名\t\t到达时间\t服务时间\t完成时间\t周转时间\t带权周转时间\n");
	int sum_t1=0;//代表总的周转时间
	double sum_t2=0;//代表总的带权周转时间
	for(i=0;i<n;i++)
	{
		p[i].turnaround_t=p[i].finish_t-p[i].arrive_t;//周转时间=完成时间-到达时间
        p[i].w_turnaround_t=(double)p[i].turnaround_t/p[i].service_t;//带权周转时间=周转时间/服务时间
		sum_t1=sum_t1 + p[i].turnaround_t;
		sum_t2=sum_t2 + p[i].w_turnaround_t;
		printf("%c\t\t    %d\t\t    %d\t\t   %d\t\t   %d\t\t  %0.2f\n",p[i].pname,p[i].arrive_t,
		       p[i].service_t,p[i].finish_t,p[i].turnaround_t,p[i].w_turnaround_t);

	}
	printf("平均周转时间:%0.2f\n",(double)sum_t1/n);
	printf("平均带权周转时间:%0.2f\n",(double)sum_t2/n);

}

//高响应比优先调度算法
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
/*进程控制块*/
typedef struct{
	char pname;//进程名
	int arrive_t;//到达时间
	int service_t;//服务时间
	int finish_t;//完成时间
	int turnaround_t;//周转时间
	double w_turnaround_t;//带权周转时间
	double r;//响应比
}PCB;

PCB p[20]; //声明进程控制块
int n=6;
void init()//初始化进程信息:进程名、到达时间、服务时间
{
	p[0].pname = 'A';
	p[0].arrive_t = 0;
	p[0].service_t = 3;

	p[1].pname = 'B';
	p[1].arrive_t = 2;
	p[1].service_t = 4;

	p[2].pname = 'C';
	p[2].arrive_t = 3;
	p[2].service_t = 2;

	p[3].pname = 'D';
	p[3].arrive_t = 4;
	p[3].service_t = 5;

	p[4].pname = 'E';
	p[4].arrive_t = 5;
	p[4].service_t = 3;
	
	p[5].pname = 'F';
	p[5].arrive_t = 6;
	p[5].service_t = 6;
}
void original_P()//输出初始状态
{
	printf("进程初始状态\n");
	printf("------------------------------------------------------------------\n");
	printf("进程名\t\t到达时间\t服务时间\n");
	int i;
	for(i=0;i<n;i++)
	{
		printf("%c\t\t    %d\t\t    %d\n",p[i].pname,p[i].arrive_t,p[i].service_t);
	}
 }
bool cmp1(PCB a,PCB b)
{
    return a.arrive_t<b.arrive_t;//按到达时间从小到达排序
}
bool cmp2(PCB a,PCB b)
{
    return a.r>b.r;//按响应比从大到小排序
}

 //高响应比优先调度算法
 void HRRN_work()
 {
    sort(p,p+n,cmp1);//先按到达时间排序
    p[0].finish_t=p[0].arrive_t+p[0].service_t;//第一个进程的完成时间=到达时间+服务时间
    int cnt;//为了计算要排序的响应比对应的进程数
    for(int i=1;i<n;i++)
    {
        cnt=0;
        for(int j=i;j<n;j++)//从当前进程的下一个进程开始看
        {
            if(p[j].arrive_t<=p[i-1].finish_t)//比较到达时间和上一个进程的完成时间
            {
                p[j].r=(double)(p[i-1].finish_t-p[j].arrive_t)/p[j].service_t+1;//计算响应比
                cnt++;

            }
            else //后面的进程还没到,就不计算了
                break;

        }
        sort(p+i,p+i+cnt,cmp2);//只需要排当前进程后面未执行的进程,按响应比由高到低排序,最大的排在前面
        //按响应比最高的执行
        p[i].finish_t=max(p[i-1].finish_t,p[i].arrive_t)+p[i].service_t;//计算进程的完成时间
    }

 }
 bool cmp3(PCB a,PCB b)
{
    return a.pname<b.pname;//按进程名排序 
}
 void Print()
{
    int i;
    printf("进程执行顺序为:\n");
	for(i=0;i<n;i++)
    {
        printf("%c ",p[i].pname);
    }
    printf("\n");
    sort(p,p+n,cmp3);
	printf("--------------------------------------------------------------------------------------------------\n");
	printf("进程名\t\t到达时间\t服务时间\t完成时间\t周转时间\t带权周转时间\n");
	int sum_t1=0;//代表总的周转时间
	double sum_t2=0;//代表总的带权周转时间
	for(i=0;i<n;i++)
	{
	    p[i].turnaround_t=p[i].finish_t-p[i].arrive_t;//周转时间=完成时间-到达时间
        p[i].w_turnaround_t=(double)p[i].turnaround_t/p[i].service_t;//带权周转时间=周转时间/服务时间
		sum_t1=sum_t1 + p[i].turnaround_t;
		sum_t2=sum_t2 + p[i].w_turnaround_t;
		printf("%c\t\t    %d\t\t    %d\t\t   %d\t\t   %d\t\t  %0.2f\n",p[i].pname,p[i].arrive_t,
		       p[i].service_t,p[i].finish_t,p[i].turnaround_t,p[i].w_turnaround_t);

	}
	printf("平均周转时间:%0.2f\n",(double)sum_t1/n);
	printf("平均带权周转时间:%0.2f\n",(double)sum_t2/n);

}
int main()
{
    init();
    original_P();
    HRRN_work();
    Print();
    return 0; 
}
//RR时间片轮转与HPF优先级调度算法
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef struct{
	char pname;//进程名
	int arrive_t;//到达时间
	int service_t;//服务时间
	int finish_t;//完成时间
	int turnaround_t;//周转时间
	double w_turnaround_t;//带权周转时间
	char state;//进程状态: w:等待, m:就绪,r:运行
	int priority;//优先级
	int run_t;//运行时间
	int remaining_t;//剩余时间
}PCB;
PCB p[20];
int n=10;
char op;
void init()//初始化进程信息:进程名、到达时间、服务时间、状态
{
	p[0].pname = 'A';
	p[0].arrive_t = 0;
	p[0].service_t = 3;
	p[0].priority=2;

	p[1].pname = 'B';
	p[1].arrive_t = 2;
	p[1].service_t = 5;
	p[1].priority=1;

	p[2].pname = 'C';
	p[2].arrive_t = 2;
	p[2].service_t = 2;
	p[2].priority=4;

	p[3].pname = 'D';
	p[3].arrive_t = 4;
	p[3].service_t = 4;
	p[3].priority=3;

	p[4].pname = 'E';
	p[4].arrive_t = 4;
	p[4].service_t = 1;
	p[4].priority=10;

	p[5].pname = 'F';
	p[5].arrive_t = 4;
	p[5].service_t = 4;
	p[5].priority=8;

    p[6].pname = 'G';
	p[6].arrive_t = 6;
	p[6].service_t = 2;
	p[6].priority=9;

	p[7].pname = 'H';
	p[7].arrive_t = 6;
	p[7].service_t = 6;
	p[7].priority=6;

	p[8].pname = 'I';
	p[8].arrive_t = 6;
	p[8].service_t = 5;
	p[8].priority=7;

	p[9].pname = 'J';
	p[9].arrive_t = 6;
	p[9].service_t = 2;
	p[9].priority=5;


	for(int i=0;i<n;i++)
    {
        p[i].state='w';//初始状态都设为等待
        p[i].run_t=0;
        p[i].remaining_t=p[i].service_t;
    }
}
void original_HPF_P()//输出HPF的初始状态
{
	printf("进程的初始状态\n");
	printf("------------------------------------------------------------------\n");
	printf("进程名\t\t到达时间\t服务时间\t优先级(数越大优先级越高)\n");
	int i;
	for(i=0;i<n;i++)
	{
		printf("%c\t\t    %d\t\t    %d\t\t    %d\n",p[i].pname,p[i].arrive_t,p[i].service_t,p[i].priority);
	}
 }
 void original_RR_P()//输出时间片轮转调度算法各进程的初始状态
{
	printf("进程的初始状态\n");
	printf("------------------------------------------------------------------\n");
	printf("进程名\t\t到达时间\t服务时间\n");
	int i;
	for(i=0;i<n;i++)
	{
		printf("%c\t\t    %d\t\t    %d\n",p[i].pname,p[i].arrive_t,p[i].service_t);
	}
 }
//HPF非抢占式优先级调度算法
//比较后面的优先级
bool cmp1(PCB a,PCB b)//先按到达时间排序,再按优先级排序
{
     if(a.arrive_t==b.arrive_t)
     {
         return a.priority>b.priority;//数越大,优先级越高
     }
     else
     {
         return a.arrive_t<b.arrive_t;
     }
}
bool cmp2(PCB a,PCB b)//按优先级排序
{
    return a.priority>b.priority;
}

void HPF_work()
{
    sort(p,p+n,cmp1);//先按到达时间排序,再按优先级排序
    p[0].finish_t=p[0].arrive_t+p[0].service_t;//第一个进程的完成时间=到达时间+服务时间
    int cnt=1;//判断完成时间内到达的进程个数,设第一个进程已经到达
    for(int i=1;i<n;i++)//看每一个进程
    {
        if(cnt<n)
        {
             for(int j=i;j<n;j++)//看后面来的进程
            {
                if(p[j].arrive_t<=p[i-1].finish_t)//比较到达时间和上一个进程的完成时间
                {
                    cnt++;//如果已经达到就标记
                }
                else
                    break;
            }
            if(cnt>i)//需要排序时
                sort(p+i,p+cnt,cmp2);//按优先级排序
        }
        p[i].finish_t=max(p[i-1].finish_t,p[i].arrive_t)+p[i].service_t;//完成时间

    }
}

bool cmp3(PCB a,PCB b)//按到达时间排序
{
    return a.arrive_t<b.arrive_t;//按到达时间从小到达排序
}
//时间片轮转法,新来的进程应该放在就绪队列的末尾
void RR_work()
{
    int q=2;//设时间片=2
    //先按到达时间排序
    sort(p,p+n,cmp3);//把这些进程编号为0-9
    queue<int> ready_q;//就绪队列
    ready_q.push(0);//先把第一个来的放到就绪队列
    //如果到达了,就放在就绪队列中,弹出队首元素
    int temp;
    int now_time=p[0].arrive_t;//从第一个进程到达时间开始算
    int cnt=1;//第一个进程已经处理了,接下来从p[1]开始看。
    int i;
    printf("进程的执行顺序:\n");
    while(1)
    {
        if(!ready_q.empty())//如果不空,队列中有元素,就占用处理机,进入运行状态
        {
            temp=ready_q.front();//取队头元素
            printf("%c ",p[temp].pname);
            ready_q.pop();//弹出队首元素
            p[temp].run_t=p[temp].run_t+q;//运行时间
            now_time=now_time+q;
             //设有10个进程,下标是从0-9,按顺序排好序的,所以是按顺序到达的
            while(cnt<n&&p[cnt].arrive_t<=now_time)
            {
                ready_q.push(cnt);//放入队尾
                p[cnt].state='m';//进入就绪队列
                cnt++;//等待下一个进程的到达
            }
            if(p[temp].run_t<p[temp].service_t)//如果这个进程还没有运行完成,就放到队列尾部
            {

                p[temp].remaining_t=p[temp].service_t-p[temp].run_t;//剩余时间=需要的服务时间-已经运行的时间

                ready_q.push(temp);//当前的这个再次入队,放在队尾
                p[temp].state='m';//状态为就绪态
            }
            else
            {
                now_time=now_time-(p[temp].run_t-p[temp].service_t);
                p[temp].state='f';//已经执行完了
                p[temp].finish_t=now_time;
            }
        }
        for( i=0;i<n;i++)
        {
            if(p[i].state=='m'||p[i].state=='w')//如果还有进程是等待或者就绪态,就继续进行时间片轮转
                break;
        }
        if(i==n)//如果都执行完了
            break;
    }
    printf("\n");
}
bool cmp4(PCB a,PCB b)
{
    return a.pname<b.pname;//按进程名从小到达排序
}
void Print()
{
    int i;
    if(op=='h'||op=='H')
    {
        printf("进程执行顺序为:\n");
        for(i=0;i<n;i++)
        {
            printf("%c ",p[i].pname);
        }
        printf("\n");
    }
    sort(p,p+n,cmp4);
	printf("--------------------------------------------------------------------------------------------------\n");
	printf("进程名\t\t到达时间\t服务时间\t完成时间\t周转时间\t带权周转时间\n");
	int sum_t1=0;//代表总的周转时间
	double sum_t2=0;//代表总的带权周转时间
	for(i=0;i<n;i++)
	{
	    p[i].turnaround_t=p[i].finish_t-p[i].arrive_t;//周转时间=完成时间-到达时间
        p[i].w_turnaround_t=(double)p[i].turnaround_t/p[i].service_t;//带权周转时间=周转时间/服务时间
		sum_t1=sum_t1 + p[i].turnaround_t;
		sum_t2=sum_t2 + p[i].w_turnaround_t;
		printf("%c\t\t    %d\t\t    %d\t\t   %d\t\t   %d\t\t  %0.2f\n",p[i].pname,p[i].arrive_t,
		       p[i].service_t,p[i].finish_t,p[i].turnaround_t,p[i].w_turnaround_t);

	}
	printf("平均周转时间:%0.2f\n",(double)sum_t1/n);
	printf("平均带权周转时间:%0.2f\n",(double)sum_t2/n);

}

int main()
{
    printf("请输入要使用的调度算法(<h/H:HPF> <r/R:RR>):");
    scanf("%c",&op);
    getchar();
    init();

    if(op=='h'|| op=='H')
    {
        original_HPF_P();
        HPF_work();
        Print();
    }
    if(op=='r'||op=='R')
    {
        original_RR_P();
        RR_work();
        Print();
    }
    return 0;
}

详细实验分析和实验报告下载:
https://download.csdn.net/download/QinHebtu/45045191

;