操作系统之设计一个按照优先级调度算法实现处理机调度的程序

要求
1.假设系统有n个进程,每个进程用一个进程控制块(PCB)来代表。进程控制块的格式如下表所示,且参数意义也相同。进程的优先数、到达时间和估计运行时间由用户程序任意设定,且优先数越低,优先级越高。调度时,总是选择优先级最高的进程运行。

2.绪队列的第一个到达进程。另外再设一个当前运行进程指针,指向当前正运行的进程。

3.处理机调度时,总是选择已经到达队列的优先级最高的进程运行。为了采用动态优先级调度,进程每运行一次,其优先级就减1。

4.由于本题目是模拟实验,所以对被选中的进程并不实际启动运行,而只是执行如下操作:
1)优先数加1;
2)估计运行时间减1;
3)输出当前运行进程的名字。
用这三个操作来模拟进程的一次运行。

5.进程运行一次后,应判断该进程的剩余运行时间是否为0,若不为0,且其优先级低于就绪队列的其他进程的优先级,则选择一个高优先级进程抢占CPU运行,若该进程的剩余运行时间为0,则将该进程的状态置为完成状态“C”,并撤出就绪队列。

6.若就绪队列不为空,则重复上述的步骤(4)和(5)直到所有进程都运行完为止。

7.在所设计的调度程序中,应包含显示或打印语句,以便显示或打印每次选中进程的名称及运行一次后进程的变化以及就绪队列中各进程排队情况。

实现代码思路
为每一个进程PCB创建一个线程来模拟其进程。每当选出一个适合运行的进程时,则模拟该进程的线程执行上面的三个操作。在执行这三个操作之间要进行加锁,即线程间互斥,以此来保证同一时刻只有一个线程在运行。

实验心得
1.加锁和解锁一定要对称。运时时程序发生死锁,表现为程序停止运行,但不退出程序,就要考虑加锁和解锁是否对称,是否存在加锁了却没有解锁的情况。
2.程序停止运行,但不退出程序还有另一种情况就是pthread_join(tid[i], NULL); 在等待线程终止,但线程已经不能再运行了。这时就要考虑线程终止的条件是否合适。
3.在设计线程并发并且线程内要循环运行互斥运行某段代码时,要使用两个while()语句来实现循环,例如下面代码的

 while (1)
  {     
  while (RunningPro->name == name && mark == 0)
   {
    //循环代码
   }
  }

代码

#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#define MaxProNum 1000

struct PCB//进程控制块信息
{
	int name;//进程名 
	struct PCB *next;//链接指针 
	int RunTime;//估计运行时间 
	int ArriveTime;//到达时间  
	int PN;//进程优先级 
	char state;//进程状态  
};
 
int Time = 0;//时钟  
int mark = 1;//当mark==1时,表示被选中的进程已经运行完。当mark==0,已经选出下一次运行的进程  
int AllProNum_copy;
int RunningProNum=0;//当前运行的线程数量
pthread_mutex_t mutex;//互斥信号量  
struct PCB temp[MaxProNum];//保存每个进程的PCB的数组 
struct PCB *RunningPro = NULL;//指向正在运行的进程的PCB的指针 
struct PCB *TailPro = NULL;//指向就绪队列第一个进程的PCB的指针 
struct PCB *HeadPro = NULL;//指向就绪队列最后一个进程的PCB的指针 
void *threadprocess(void *arg)
{
	int name = *(int *)arg;
	while (1)
 	{     
		while (RunningPro->name == name && mark == 0)
 		{
			pthread_mutex_lock(&mutex);//加锁          
			printf("进程%d正在运行\n", name);
			RunningPro->PN = RunningPro->PN + 1;//进程优先级数+1
			RunningPro->RunTime = RunningPro->RunTime - 1;//进程运行时间-1       
			mark = 1;        
			if (RunningPro->RunTime == 0)//若进程运行完
			{
                		RunningPro->state = 'C';//将进程状态置为'C'
               			AllProNum_copy--;
                		printf("进程%d完成退出\n", name);
                		printf("\n\n");
				pthread_mutex_unlock(&mutex);//解锁
                		pthread_exit(NULL);//终止进程         
			}           
			pthread_mutex_unlock(&mutex);//解锁	
          		printf("\n\n");           
			break;      
		}      
		sleep(0);
  	 }
}

 

int main()
{   
	pthread_t tid[MaxProNum];   
	int M[MaxProNum];  
	pthread_mutex_init(&mutex, NULL);//初始化互斥量
	int AllProNum;//设置总进程数   
	printf("请输入进程数:");   
	scanf("%d",&AllProNum);   
	AllProNum_copy = AllProNum;  
	printf("**********进程信息**********\n");   
	for (int i = 0; i < AllProNum; i++)
    	{   
		temp[i].name = i;       
		temp[i].next = NULL;		 
		temp[i].RunTime = rand() % 10+1;      
		temp[i].ArriveTime = rand() % 50+2;       
		temp[i].PN = rand() % 10;       
		temp[i].state = 'R';       
		M[i] = i;       
		printf("进程名:%d    到达时间:%d    运行时间:%d    优先级数:%d    状态:%c\n",temp[i].name,temp[i].ArriveTime,temp[i].RunTime,temp[i].PN,temp[i].state);
	 }   
	 int mark1 = 0;  
	 while (AllProNum_copy)
    	 {       
		while (mark == 1)       
		{           
			pthread_mutex_lock(&mutex);          
			printf("**********时间:%d**********\n",Time);           
			if(AllProNum_copy==0)//如果全部进程运行完
                		break;                      
			for (int i = 0; i < AllProNum; i++)//该循环将到达时间为现在时间的线程放入队列        
   			{
                		if (temp[i].ArriveTime == Time)
               			 {                    
                   			 RunningProNum++;
                   			 if (HeadPro==NULL)//如果这是第一个线程
                    			 {
                        			HeadPro = TailPro =&temp[i];//令头指针和尾指针都指向它                       
						pthread_create(&tid[i], NULL, threadprocess, (void *)&M[i]);//为该进程生成一个线程
                    			 }
                    		 	else
                    		 	{
	               				TailPro->next = &temp[i];//尾插法
	                        		temp[i].next = NULL;
	                        		TailPro = &temp[i];                       
						pthread_create(&tid[i], NULL, threadprocess, (void *)&M[i]);//为该进程生成一个线程
	                    		 }
                		  }           
			  }
           
			 if(HeadPro==NULL)//如现在没有进程则直接跳过           
			 {
                		Time++;
                		printf("无进程运行\n\n");               
				pthread_mutex_unlock(&mutex);//加锁
	                	continue;           
			 }	
           
			 struct PCB *RunPro = NULL;           
			 struct PCB *tmp = HeadPro;           
			 struct PCB *last = HeadPro;           
			 int minPN = 1024;
	           
			 while (tmp != NULL)//获得就绪队列和优先级数最小的线程           
			 {
	                	if (tmp->state == 'C')//如果线程状态为C,则将该线程从就绪队列中移除
	                	{
	                    		RunningProNum--;
	                    		if(RunningProNum==0)//如果当前运行进程数为0
	                    		{
	                        		HeadPro=TailPro=NULL;
	                        		break;
	                    		} 
	                    		if(tmp==HeadPro)//如果需要移去的是头节点
	                    		{                       
						HeadPro=HeadPro->next;
	                        		tmp = HeadPro;
	                    		}
	                    		else if (tmp==TailPro)//如果需要移去的是尾节点
	                    		{
	                        		TailPro = last;
	                        		last->next=NULL;
	                        		break;
	                    		}
	                    		else//如果需要移去的是其他节点
	                    		{
	                        		last->next =tmp->next;
	                        		tmp = tmp->next;
	                    		}
	                    		continue;
	                	} 
	                	printf("(名字%d 优先数%d 运行时间%d)->",
				tmp->name, tmp->PN,tmp->RunTime);
	               		if (tmp->PN < minPN && tmp->RunTime != 0)//获得优先级数最小的线程
	                	{
	                    		RunPro = tmp;     
	              	    		minPN=tmp->PN;
	                	}
	                	last = tmp;
	                	tmp = tmp->next;           
			}           
			if(RunningProNum==0) //如果当前运行进程数为0          
			{
		                Time++;               
				pthread_mutex_unlock(&mutex);//解锁
		                continue;           
			}           
			RunningPro = RunPro;//将RunningPro置为下次运行的进程的PCB地址            
			printf("\n最适合运行的线程:%d\n",
			RunningPro->name);                         
			Time++;                      
			mark = 0;             
			pthread_mutex_unlock(&mutex);//解锁           
			sleep(0);       
		}       
		if(AllProNum_copy==0)           
		break;
    	}     
    	printf("全部线程完成\n");   
    	for (int i = 0; i < AllProNum; i++)//等待所有线程结束       
    		pthread_join(tid[i], NULL);   
    	return 0;
}
  • 4
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、实验目的 多道系统中,进程与进程之间存在同步与互斥关系。当就绪进程大于处理机时,需按照某种策略决定哪些进程先占用处理机。在可变分区管理方式下,采用首次适应算法实现主存空间的分配和回收。 本实验模拟实现处理机调度及内存分配及回收机制,以对处理机调度的工作原理以及内存管理的工作过程进行更深入的了解。 二、实验内容及要求 1.实验内容 (1)选择一个调度算法实现处理机调度; (2)结合(1)实现主存储器空间的分配和回收。 2.实验具体要求 (1)设计一个抢占式优先调度算法实现处理机调度程序,并且实现在可变分区管理方式下,采用首次适应算法实现主存空间的分配和回收。 (2)PCB内容包括:进程名/PID;要求运行时间(单位时间);优先权;状态;进程属性:独立进程、同步进程(前趋、后继)。 (3)可以随机输入若干进程,可随时添加进程,并按优先权排序; (4)从就绪队首选进程运行:优先权-1;要求运行时间-1;要求运行时间为0时,撤销该进程;一个时间片结束后重新排序,进行下轮调度; (5)考虑两个处理机,考虑同步进程的处理机分配问题,每次调度后,显示各进程状态,运行进程要显示在哪个处理机上执行。 (6)规定道,设置后备队列和挂起状态。若内存中进程少于规定道,可自动从后备队列调度一作业进入。被挂起进程入挂起队列,设置解挂功能用于将制定挂起进程解挂入就绪队列。 (7)结合实验一pcb增加所需主存大小,主存起始位置;采用首次适应算法分配主存空间。 (8)自行假设主存空间大小,预设操作系统所占大小并构造未分分区表。表目内容:起址、长度、状态(未分/空表目)。 (9)进程完成后,回收主存,并与相邻空闲分区合并。 (10)最好采用图形界面;
1. 实验目的 调度的实质是操作系统按照某种预定的策略来分配资源。进程调度的目的是分配CPU资源。由于进程调度程序执行的频率很高,因此调度算法的好坏直接影响到操作系统的性能。本实验的目的是编程模拟实现几种常用的进程调度算法,通过对几组进程分别使用不同的调度算法,计算进程的平均周转时间和平均带权周转时间,比较各种算法的性能优劣。 2. 实验原理 [1]. 进程调度算法描述 进程调度算法包括先来先服务调度算法、最短作业时间优先(抢占式和非抢占式)、最高响应比调度算法4种。(每个人必须做FCFS,然后在后面的三种中任选一种,即每个人必须做2种调度算法的模拟。) [2]. 衡量算法性能的参 计算进程的平均周转时间和平均带权周转时间。 3. 实验内容 (1)编程实现本实验的程序,要求: [1]. 建立进程的进程控制块,进程控制块至少包括: a) 进程名称; b) 进程需要执行时间; c) 进入就绪队列时间; d) 进程执行开始时间 e) 进程执行结束时间 [2]. 编程实现调度算法。 [3]. 进程及相关信息的输入。这些信息可以直接从键盘上输入,也可以从文件读取。 [4]. 时间片与时间流逝的模拟。本实验需要对算法的执行计时,程序应该提供计算时间的方法。一种最简单的方法是使用键盘,比如每敲一次空格代表一个时间片的流逝。另一种方法是使用系统时钟。 [5]. 一组进程序列执行完毕,打印出结果信息。程序需要计算出每个进程的开始执行时间、结束时间、周转时间和带权周转时间,并为整个进程序列计算平均周转时间和平均带权周转时间。程序将计算结果按一定的格式显示在计算机屏幕上或输出到文件中。打印出进程调度顺序图。 [6]. 实现据在磁盘文件上的存取功能。 (2)对下列就绪进程序列分别使用上面的几种算法进行调度,计算每种算法下的平均周转时间和平均带权周转时间。 进程号 到达时间 要求执行时间 0 0 1 1 1 35 2 2 10 3 3 5 4 6 9 5 7 21 6 9 35 7 11 23 8 12 42 9 13 1 10 14 7 11 20 5 12 23 3 13 24 22 14 25 31

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值