操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)

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);

以上是关于操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)的主要内容,如果未能解决你的问题,请参考以下文章

时间片轮转算法和优先级调度算法模拟实现

时间片轮转算法和优先级调度算法 C语言模拟实现

进程调度算法

OS(A)之进程调度模拟算法

操作系统进程

操作系统进程