操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)
Posted JINKELA_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)相关的知识,希望对你有一定的参考价值。
实验二 进程调度
一、 实验目的
1. 理解进程运行的并发性。
2. 理解处理器的三级调度。
3. 掌握先来先服务的进程调度算法。
4. 掌握短进程优先的进程调度算法。
5. 掌握时间片轮转的进程调度算法。
二、 实验设备
1. 安装windows或者linux操作系统的PC机
2. C程序编译环境
三、 实验内容
用c语言编程模拟实现至少一个操作系统的常见进程调度算法。常见的进程调度算法有先来先服务、短进程优先、时间片轮转法等。
四、 实验要求
1. 上机编写并调试进程调度的模拟程序。
2. 要把相应的程序代码及程序运行结果写入实验报告中。
//操作系统—进制控制模拟
#include<stdio.h>
#include<stdlib.h>
#include <windows.h>
#include<tlhelp32.h>
#define N 10
struct pb
int ko;
int no;
int cha;
;
typedef struct pb PCB;
PCB a[N];
int showallproc()
PROCESSENTRY32 pe32;//用来存储进程信息的结构体
pe32.dwSize=sizeof(pe32);
HANDLE hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获取进程快照
if(hProcessSnap==INVALID_HANDLE_VALUE)
printf("调用失败\\n");
return 1;
BOOL bProc=Process32First(hProcessSnap,&pe32);
while(bProc)
printf("%5d %s\\n",pe32.th32ProcessID,pe32.szExeFile);//输出进程ID和进程名
bProc=Process32Next(hProcessSnap,&pe32);
CloseHandle(hProcessSnap);
return 0;
static int count=1;
void create() //创建
static int pi=1;
int k,l=0,m;
printf("请输入创建的进程号:");
scanf("%d",&m);
for(k= 1;k<= N;k++ )
if(a[k].no ==m)
l=1;
if(l == 1)
printf("错误,进程创建重复!\\n");
create();
else
for(k= 1;k<= N;k++ )
if(a[k].no==0)
pi=k;break;
a[pi].no=m;
printf("\\n输入优先级:");
scanf("%d",&a[pi].ko);
if(count>1) //首次进程状态为执行,之后为活动就绪
a[pi++].cha=3;
else
a[pi++].cha=5;
count++;
int stopproc()
DWORD ProcessID;
printf("请输入想要终止的进程ID\\n");
scanf(" %d",&ProcessID);
HANDLE hProcess=OpenProcess(PROCESS_TERMINATE,FALSE,ProcessID);//打开对应进程句柄
if (hProcess==NULL)
printf("失败\\n");
return -1;
if (!TerminateProcess(hProcess,0))//关闭进程
printf("关闭失败\\n");
else
printf("关闭成功\\n");
CloseHandle(hProcess);
return 0;
void dispatch() //调度
int i,m,l=0,j=0,k,min=10000;
for(m= 1;m<= N;m++ )
if(a[m].cha==5)
l=m;
if(l!=0)
printf("调度失败!");
return;
else
for(k= 1;k<= N;k++ )
if(a[k].cha==3)
if(min>a[k].ko)
min=a[k].ko;
i=k;
j=1;
if(j)
a[i].cha=5;
else if(j==0)
printf("调度失败!\\n");
void block() //阻塞
int k,m,l=0;
printf("请输入已经创建的进程号:");
scanf("%d",&m);
for(k= 1;k<= N;k++ )
if(a[k].no==m)
l=k;
if(l!=0)
if(a[l].cha==3 || 5)
a[l].cha=4;
else if(a[l].cha==1)
a[l].cha=2;
else
printf("阻塞失败!\\n");
else
printf("阻塞失败!");
void wakeup() //唤醒
int k,m,l=0;
printf("请输入已经创建的进程号:");
scanf("%d",&m);
for(k= 1;k<= N;k++ )
if(a[k].no==m)
l=k;
if(l!=0)
if(a[l].cha==2)
a[l].cha=1;
else if(a[l].cha==4)
a[l].cha=3;
else
printf("唤醒失败!\\n");
else
printf("唤醒失败!");
void suspend() //挂起
int k,m,l=0;
printf("请输入已经创建的进程号:");
scanf("%d",&m);
for(k= 1;k<= N;k++ )
if(a[k].no==m)
l=k;
if(l!=0)
if(a[l].cha==3 || 5)
a[l].cha=1;
else if(a[l].cha==4)
a[l].cha=2;
else
printf("错误!挂起失败\\n");
else
printf("错误!挂起失败!");
void active() //激活
int k,m,l=0;
printf("请输入已经创建的进程号:");
scanf("%d",&m);
for(k= 1;k<= N;k++ )
if(a[k].no==m)
l=k;
if(l!=0)
if(a[l].cha==1)
a[l].cha=3;
else if(a[l].cha==2)
a[l].cha=4;
else
printf("激活失败!\\n");
else
printf("激活失败!");
void display() //查看PCB功能模块
int i;
printf("\\t\\tPCB\\t进程号\\t优先级\\t状态\\n");
for(i= 1;i<= 10;i++ )
printf("\\t\\t%d\\t%d\\t%d\\t%d\\n",i,a[i].no,a[i].ko,a[i].cha);
printf("\\t1-静止就绪 2--静止阻塞 3--活动就绪 4--活动阻塞 5--执行\\n");
void change_KO() //改变优先数
int k,m,l=0;
printf("请输入已创建的进程号:");
scanf("%d",&m);
for(k= 1;k<= N;k++ )
if(a[k].no==m)
l=k;
if(l!=0)
printf("输入新的优先级:");
scanf("%d",&a[l].ko);
display();
else
printf("失败!");
/********************这是先来先服务的程序*********************************/
struct fcfs//定义先来先服务结构体、参数
char name[10];
float daodatime;//到达时间
float fuwutime;//服务时间
float kaishitime;//开始时间
float wanchengtime;//完成时间
float zhouztime;//周转时间
float daiquantime;//带权周转时间
;
fcfs b[10000];
void input(fcfs *p,int N1) //构造一个输入进程的信息的函数,定义结构体指针
int i;
for(i=0;i<=N1-1;i++)
printf("输入第%d个进程的名字、到达时间、服务时间:\\n",i+1);
scanf("%s%f%f",&p[i].name,&p[i].daodatime,&p[i].fuwutime);//把输入的信息保存到结构体指针所对应的内存中
//构造一个输出函数
void Print(fcfs *p,float daodatime,float fuwutime,float kaishitime,float wanchengtime,float zhouztime,float daiquantime,int N1)
int k;
printf("执行顺序:\\n");
printf("%s",p[0].name);
for(k=1;k<N1;k++)
printf("-->%s",p[k].name);
printf("\\n进程的相关信息如下:\\n");
printf("\\n名字\\t到达\\t服务\\t开始\\t完成\\t周转\\t带权周转\\n");
for(k=0;k<=N1-1;k++)
printf("%s\\t%-.2f\\t%-.2f\\t%-.2f\\t%-.2f\\t%-.2f\\t%-.2f\\t\\n",p[k].name,p[k].daodatime,p[k].fuwutime,p[k].kaishitime,p[k].wanchengtime,p[k].zhouztime,p[k].daiquantime);
//题目中加入-.2是保留双精度的两位。一般f默认保留六位小数的。
void sort(fcfs *p,int N1)//进程根据到达时间进行排序
for(int i=0;i<=N1-1;i++)
for(int j=0;j<=i;j++)
if(p[i].daodatime<p[j].daodatime)//如果i的时间到达时间小于j的到达时间,就交换
fcfs temp;//在结构体中定义第三个变量进行交换
temp=p[i];
p[i]=p[j];
p[j]=temp;
//核心的运行阶段
void deal(fcfs *p, float daodatime,float fuwutime,float kaishitime,float wanchengtime,float zhouztime,float daiquantime,int N1)
int k;
for(k=0;k<=N1-1;k++)
if(k==0)//K=0,表示第一个进程到达
p[k].kaishitime=p[k].daodatime;//那么开始时间=到达时间
p[k].wanchengtime=p[k].daodatime+p[k].fuwutime;//完成时间=到达时间+服务时间
else
p[k].kaishitime=p[k-1].wanchengtime;//下一个进程的开始时间=上一个进程的完成时间
p[k].wanchengtime=p[k-1].wanchengtime+p[k].fuwutime;//完成时间=上一个进程的完成时间+服务时间
for(k=0;k<=N1-1;k++)//计算周转时间和带权周转时间
p[k].zhouztime=p[k].wanchengtime-p[k].daodatime;//周转时间=完成时间-到达时间
p[k].daiquantime=p[k].zhouztime/p[k].fuwutime;//带权周转时间=周转时间/服务时间
void FCFS(fcfs *p,int N1)//定义先来先服务函数
float daodatime=0,fuwutime=0,kaishitime=0,wanchengtime=0,zhouztime=0,daiquantime=0;//初始化变量为0
sort(p,N1);//声明排序函数
deal(p,daodatime,fuwutime,kaishitime,wanchengtime,zhouztime,daiquantime,N1);//声明运行函数
Print(p,daodatime,fuwutime,kaishitime,wanchengtime,zhouztime,daiquantime,N1); //声明输出函数
/****************************这是优先服务调度算法的代码***********************************/
typedef struct PCB2
char name[10];//进程名
int runtime;//要求运行时间
int frist;//定义优先数
char zhuangtai; //定义状态,R为就绪,F为完成
;
struct PCB2 PCBcontrol[4];//定义进程控制块数组
void youxian()//构造优先函数
int i,n;
printf("请输入进程的个数:\\n");
scanf("%d",&n);
printf("请输入进程的名字、优先权、运行时间\\n");
printf("\\n");
for(i=0;i<n;i++)
printf("请输入第%d个进程的信息:\\n",i+1);
scanf("%s%d%d",&PCBcontrol[i].name,&PCBcontrol[i].frist,&PCBcontrol[i].runtime);
PCBcontrol[i].zhuangtai='R';//进程初始状态均为就绪
getchar();//等待回车进入下一次运行
int max_frist_process()//确定最大优先级进程子程序
int max=-10;//max为最大优先数,初始化为-10
int i,key;
for(i=0;i<3;i++)
if(PCBcontrol[i].zhuangtai=='r')//r表示正在运行
return -1;//返回-1
else
if(max<PCBcontrol[i].frist&&PCBcontrol[i].zhuangtai=='R')//从就绪进程中选取优先数最大的进程
max=PCBcontrol[i].frist;//max存放每次循环中的最大优先数
key=i;//将进程号赋给key
if(PCBcontrol[key].zhuangtai=='F')//具有最大优先数的进程若已运行完毕
return -1;//则返回-1
else
return key;//将key作为返回值返回
void show()//显示函数
int i;
printf("\\n进程名 优先级 运行时间 当前状态\\n");
printf("*****************************************\\n");
for(i=0;i<3;i++)//依次显示每个进程的名、优先数、要求运行时间和状态
printf(" %s\\t %d\\t %d\\t %s\\t\\n",&PCBcontrol[i].name,PCBcontrol[i].frist,PCBcontrol[i].runtime,&PCBcontrol[i].zhuangtai);
printf("\\n请按回车键进行查看");
void run()//进程运行子程序
int i,j;
int t=0;//t为运行次数
for(j=0;j<3;j++)
t+=PCBcontrol[j].runtime;//运行次数即为各个进程运行时间之和
printf("\\n进程没运行前,当前的状态是:\\n");
show(); //调用show()子程序显示运行前PCB的情况
getchar();//等待回车进入下一次运行
for(j=0;j<t;j++)
while(max_frist_process()!=-1)//具有最大优先数的进程没有运行完,让其运行
PCBcontrol[max_frist_process()].zhuangtai='r';//将其状态置为r,表示其正在运行
for(i=0;i<3;i++)
if(PCBcontrol[i].zhuangtai=='r')
PCBcontrol[i].frist-=1;//将当前运行进程的优先数减1
PCBcontrol[i].runtime--;//要求运行时间减1
if(PCBcontrol[i].runtime==0)
PCBcontrol[i].zhuangtai='F';//运行完则将该进程状态置为结束
else
PCBcontrol[i].zhuangtai='R';//未运行完将其状态置为就绪
show();//显示每次运行后各PCB的情况
getchar();//等待回车进入下一次运行
/***********************这是算法时间片轮转法的代码*****************************************/
struct shijian //定义时间片的结构体
char name; //定义进程名
int daodatime;// 到达时间
int fuwutime; //服务时间
int shengyutime;//剩余时间
char *state;//所处状态
struct shijian *next;
;
struct shijian *time()
int a,i;
struct shijian *head, *rear,*p,*q,*t;//定义队首、队尾、P是队尾指针、Q是队首指针和执行时间
head=rear=NULL;//初始化队首和队尾为空
printf("请输入进程数目:");
scanf("%d",&a);
for(i=0;i<a;i++)
p=(struct shijian*)malloc(sizeof(struct shijian)); //初始化一个空间给进程进入
printf("输入第%d个进程的名字、到达时间、服务时间:\\n",i+1);
scanf("%s%d%d",&p->name,&p->daodatime,&p->fuwutime);
p->shengyutime=p->fuwutime;
p->state="就绪";
if(rear==NULL) //当输入结束时,把P的数据放到队首,以便执行下一步
head=p;
p->next=NULL;
rear=p;
else //否则执行时间就为空,队首变成Q
t=NULL;
q=head;
while(q&&q->daodatime<p->daodatime)//当Q和Q的到达时间小于P的到达时间时,把执行时间给Q
t=q;
q=q->next;
if(q==head) //而当Q是队首时,则下一个队首变成P,以便每个进程都能够得到时间片
p->next=head;
head=p;
else if(t==rear) //当执行时间片到达队尾时(执行完时),返回给队首P
rear->next=p;
p->next=NULL;
rear=p;
else //否则给队首P占用执行时间,P执行完后到Q
t->next=p;
p->next=q;
return head;//返回队首
void output(struct shijian *head)//定义输出函数
struct shijian *p,*t,*r;
int num;
printf("请输入时间片:");
scanf("%d",&num);
while(head!=NULL) //当队首不为空时,把P给队首
r=p=head;
while(p!=NULL) //把执行时间给队首
t=head;
p->shengyutime=p->shengyutime-num; //P的剩余时间=剩余时间-时间片
p->state="运行"; //状态变成运行态
if(p->shengyutime<0) //当P运行完,即剩余时间小于0时,仍然把它当做0处理
p->shengyutime=0;
printf("\\n************程序开始运行*****************\\n");
printf("进程 到达时间 服务时间 剩余时间 当前状态\\n");
while(t!=NULL) //时间不为空时,输出当前进程的信息,并把时间片交给下一个进程
printf("%2c%8d%8d%14d%10s\\n",t->name,t->daodatime,t->fuwutime,t->shengyutime,t->state);
t=t->next;
getchar(); //按住回车键观看
if(p->shengyutime==0)//当队首的剩余时间为0时,先把队首改成P的下一个,然后释放内存,删除队首节点
if(p==head)
head=p->next;
free(p);
p=head;
else //否则返回执行,把队尾的下一个指针变成P的下一个指针,队尾的位置移动到队首
r->next=p->next;
p=r->next;
r=p;
else //否则把队首的位置给队尾,把队首的状态显示为"就绪"状态
r=p;
p->state="就绪";
p=p->next;
void diaodusuanfa()
int N1;
int number;
char Tishikuang;//提示框
do
printf(" ** 输入 1-先来先服务 *\\n");
printf(" ** 输入 2-时间片轮转法 *\\n");
printf(" ** 输入 3-优先服务法 *\\n");
printf(" ** 输入 0-退出该程序 *\\n");
printf("\\n提示:请根据自己的需求选择相应的操作数:\\n");
scanf("%d",&number);/*提示输入字母,用switch语句存入到case中,最后增加提示框是否继续*/
switch(number)
case 0:
break;
case 1:
printf("您选择的是**先来先服务调度**\\n\\n");
printf("请输入进程的数量:\\n");
scanf("%d",&N1);
input(b,N1);
FCFS(b,N1);
break;
case 2:
printf("\\n您选择的是时间片轮转发调度\\n\\n");
struct shijian *head; //定义时间片的队首结构体
head=time(); //队首执行的时间
output(head) ;//输出函数
break;
case 3:
printf("\\n您选择的是优先服务调度,本程序可提供3个进程的调度。\\n\\n");
youxian();//初始化各个进程PCB
run();//进程调度模拟
break;
default:
printf("\\n你的输入有误,请确定是从0到3之间进行输入,O(∩_∩)O谢谢\\n");
break;
printf("\\n是否继续操作(y/n) ?");
fflush(stdin);
Tishikuang=getchar();
while(Tishikuang=='y'||Tishikuang=='Y');
int main()
int i;
do
printf("\\t\\t**************功能模块 ***************\\n");
printf("\\t\\t* 1-----进程创建 *\\n");
printf("\\t\\t* 2-----进程撤消 *\\n");
printf("\\t\\t* 3-----调度 *\\n");
printf("\\t\\t* 4-----阻塞 *\\n");
printf("\\t\\t* 5-----唤醒 *\\n");
printf("\\t\\t* 6-----挂起 *\\n");
printf("\\t\\t* 7-----激活 *\\n");
printf("\\t\\t* 8-----查看进程控制块 *\\n");
printf("\\t\\t* 9-----改变优先数 *\\n");
printf("\\t\\t* 10----查看进程 *\\n");
printf("\\t\\t* 11----调度算法模拟 *\\n");
printf("\\t\\t* 0-----退出 *\\n");
printf("\\t\\t*************************************\\n");
printf("\\t\\t请选择0-10:");
scanf("%d",&i);
printf("\\n");
switch(i)
case 1: create();break;
case 2:stopproc();break;
case 3: dispatch();break;
case 4: block();break;
case 5: wakeup();break;
case 6: suspend();break;
case 7: active();break;
case 8: display();break;
case 9: change_KO();break;
case 10: showallproc();break;
case 11: diaodusuanfa();break;
case 0: exit(0); //程序正常退出
while(i!=0);
以上是关于操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)的主要内容,如果未能解决你的问题,请参考以下文章