操作系统实验连接
实验一 进程调度算法
实验二 预防死锁-银行家算法
实验三 分区分配算法+请求式分页存储管理算法
实验四 文件系统
进程调度算法(优先数法+简单轮转法)
这学期学习了操作系统,最近开始了操作系统实验,在网上看了一篇关于进程调度的代码,但是发现有挺多错误的,所以自己改了一部分代码分享出来。
目的与要求
1.目的
进程调度是处理及管理的核心内容,本次实验要求用C语言编写和调试一个简单的进程调度程序。调度算法可以任意选择或自行设计,例如简单轮转法和优先数法等。通过本次实验可以加深各使用进程控制块进行进程调度和各种调度算法的理解及其实施方法。
2.要求
(1)在微型计算机上设计进程控制块(PCB)结构,使其分别适用于简单轮转法和优先数调度算法。PCB通常包括以下信息:进程名、进程优先数(或轮转时间片)、进程所占用的CPU时间、进程的当前状态、当前队列指针等。根据调度算法的不同,PCB结构的内容可以作适当的增删。
(2)调度程序应包含2~3种不同的调度算法,运行时可任选一种,以利于各种算法的分析比较。基本要求是:优先数调度算法和简单循环轮转法。
(3)建立进程就绪队列,对各种不同的算法编制入链子程序,同时应具有显示或打印各进程的运行状态和参数的变化情况,便于观察各进程的调度过程。
实验内容
1.题目
采用C语言编写程序,选用优先数调度算法或简单轮转法对五个进程进行调度,每个进程处于运行(Run)、就绪(Ready)和完成(Finish)三种状态之一,并假定起始状态为就绪状态。
2.算法说明
(1)优先数法
进程就绪队列按优先数大小从高到低排列,链首进程首先投入运行。进程每执行一次,进程需要的时间片数减1、该进程的优先数减3。这样,该进程如果在一个时间片中没有完成,其优先数降低一级。接着仍是用该进程降低一级后的优先数与就绪队列中链首进程的优先数进行比较,如果仍是该进程的优先数高或相同,便让该进程继续执行;否则,调度就绪队列的链首进程投入运行。原运行过的进程按其现行优先数大小插入就绪队列,且改变它们对应的进程状态,一直到所有进程都运行完各自的时间片数。
(2)简单轮转法
进程就绪队列按各进程进入的先后顺序排列。进程每次所需处理机的轮转式按其重要程度记入进程控制块中的轮转时间片数记录项。进程执行时,每运行一个时间片,进程还需要的时间片数减1,运行进程占用处理机的时间片数加1,然后比较占用CPU的时间片数是否与该进程的轮转时间片数相等,若相等则说明已达到轮转时间,应将现运行的进程排列就绪队列的末尾,调度队列上的首进程运行,且改变它们的进程状态,直至所有进程完成各自的时间片。
代码
由用户选择执行哪个算法
#include <iostream>
#include<stdio.h>
#include<malloc.h>
using namespace std;
enum process_status{READY , RUN , FINISH}; //进程的三种状态
//定义进程数据结构
typedef struct pcb
{
char process_tag[20] ; //存储进程标识符
struct pcb *next ; //连接下一个进程的指针
int num ; //优先调度算法中为优先级 , 轮转调度算法中为轮转时间片
int take_cpu_time ; //占用CPU时间片数
int process_time ; //进程所需时间片数
process_status status ; //进程当前的状态
} PCB ;
//定义进程控制块的链结构
typedef struct
{
PCB *run ; //当前运行的进程指针
PCB *ready ; //当前准备队列的头指针
PCB *tail ; //准备队列的队尾指针
PCB *finish ; //完成队列的指针
} PCBC ;
void init_pcbc(PCBC *p)
{
p->run = NULL ;
p->ready = NULL ;
p->tail = NULL ;
p->finish = NULL ;
}
void swapx(PCB * p1 , PCB *p2)
{
int i , num , take_cpu_time , process_time ;
char temp ;
//进行标识符的交换
for(i = 0 ; i < 20 ; i++)
{
temp = p1->process_tag[i];
p1->process_tag[i] = p2->process_tag[i] ;
p2->process_tag[i] = temp ;
}
//优先值的交换
num = p1->num ;
p1->num = p2->num ;
p2->num = num ;
//占用CPU时间片的交换
take_cpu_time = p1->take_cpu_time ;
p1->take_cpu_time = p2->take_cpu_time ;
p2->take_cpu_time = take_cpu_time ;
//进程所需时间片数的交换
process_time = p1->process_time ;
p1->process_time = p2->process_time ;
p2->process_time = process_time ;
}
//将就绪队列按优先级别大小进行排序,按冒泡排序算法
void sort_pcbc(PCBC *pcbc)
{
PCB *p , *p1 ;
p = pcbc->ready ;
for(p = pcbc->ready ; p != NULL ; p = p->next)
{
for(p1 = p->next ; p1 != NULL ; p1 = p1->next)
{
if(p->num < p1->num)
{
swapx(p , p1) ; //只是进行指针内部数据的交换,不改变指针指向
}
}
}
}
//输入进程,并加入就绪队列
void input_process(PCBC *pcbc)
{
PCB *pcb ;
pcb = (PCB*)malloc(sizeof(PCB)) ;
printf("请输入进程标识符:") ;
scanf("%s" , &pcb->process_tag) ;
printf("输入格式为: (优先级/轮转时间片,进程所需时间片数) : ") ;
scanf("%d,%d,%d" , &pcb->num , &pcb->process_time) ;
pcb->take_cpu_time=0;
pcb->status = READY ; //初始化就绪状态
//当就绪队列为空时
if(pcbc->ready == NULL && pcbc->tail == NULL)
{
pcbc->ready = pcbc->tail = pcb ;
pcb->next = NULL ;
}
else
{
//将新进入的队列加入队尾
pcb->next = pcbc->tail->next ;
pcbc->tail->next = pcb ;
pcbc->tail = pcb ;
}
}
/*
*打印当前进程控制块中的情况
*/
void print_log(PCBC *pcbc)
{
PCB *ready , *finish ;
ready = pcbc->ready ;
finish = pcbc->finish ;
printf("-------------------------------------------------- \n") ;
printf("Run: \n") ;
if(pcbc->run != NULL)
{
printf("%s %04d %04d %04d \n" , pcbc->run->process_tag ,pcbc->run->num , pcbc->run->take_cpu_time , pcbc->run->process_time) ;
}
else
{
printf("Run is empty! \n") ;
}
printf("Ready:\n") ;
while(ready != NULL)
{
printf("%s %04d %04d %04d \n" , ready->process_tag ,ready->num , ready->take_cpu_time , ready->process_time) ;
ready = ready->next ;
}
printf("Finish:\n") ;
while(finish != NULL)
{
printf("%s %04d %04d %04d \n" , finish->process_tag ,finish->num , finish->take_cpu_time , finish->process_time) ;
finish = finish->next ;
}
}
/*
*运行优先数法
*/
void Priority(PCBC *xpcbc)
{
PCBC *pcbc = xpcbc ;
PCB *temp , *pre , *tail ;
sort_pcbc(pcbc);//进入调度算法,首先对所有进程排序
//进入循环调度
while(pcbc->ready != NULL)
{
pcbc->run = pcbc->ready ; //将就绪队列队首加入运行队列
pcbc->ready = pcbc->ready->next ; //改变队首元素为下一个元素
print_log(pcbc) ;
pcbc->run->num -= 3 ;//将优先度减3
pcbc->run->process_time -= 1 ;//将进程所需要运行时间减1
pcbc->run->take_cpu_time+= 1;
//进程执行完
if(pcbc->run->process_time == 0)
{
if(pcbc->finish == NULL)
{
pcbc->finish = pcbc->run ;
pcbc->finish->next = NULL ;
tail = pcbc->finish ;
}
else
{
tail->next = pcbc->run ;
tail = tail->next ;
tail->next = NULL ;
}
}
//当前进程还没有执行完时
else
{
//判断下一个ready是否为空,即进程是否全部执行完
if(pcbc->ready != NULL)
{
//将run的元素再放在ready中重新排序
pcbc->run->next=pcbc->ready;
pcbc->ready=pcbc->run;
sort_pcbc(pcbc);
}
else
{
pcbc->ready = pcbc->run ;
}
}
}
pcbc->run = NULL ;
print_log(pcbc) ;
}
//简单轮转法
void TimeSlice(PCBC *xpcbc)
{
PCBC *pcbc = xpcbc ;
PCB *temp , *pre , *tail ;
//进行那个CPU的循环调用
while(pcbc->ready != NULL)
{
pcbc->run = pcbc->ready ; //将就绪队列队首加入运行队列
pcbc->ready = pcbc->ready->next ; //改变队首元素
print_log(pcbc) ;
pcbc->run->take_cpu_time += 1 ;
pcbc->run->process_time -= 1 ;
if(pcbc->run->process_time == 0)
{
if(pcbc->finish == NULL)
{
pcbc->finish = pcbc->run ;
pcbc->finish->next = NULL ;
tail = pcbc->finish ;
}
else
{
tail->next = pcbc->run ;
tail = tail->next ;
tail->next = NULL ;
}
}
else
{
if(pcbc->run->num == pcbc->run->take_cpu_time) //占用CPU时间片数到
{
//将其加入队尾
pcbc->run->take_cpu_time = 0 ;
pcbc->run->next = NULL ;
pcbc->tail->next = pcbc->run ;
pcbc->tail = pcbc->run ;
if(pcbc->ready == NULL)
{
pcbc->ready = pcbc->tail ;
pcbc->ready->next = NULL ;
}
}
else
{
pcbc->run->next = pcbc->ready ;
pcbc->ready = pcbc->run ;
}
}
}
pcbc->run = NULL ;
print_log(pcbc) ;
}
int main()
{
PCBC *pcbc ; //创建进程控制块链 ;
int pcb_num ; //记录处理进程数目
pcbc = (PCBC*)malloc(sizeof(PCBC)) ;
printf("请输入要处理的进程数目: ") ;
scanf("%d" , &pcb_num) ;
init_pcbc(pcbc) ; //初始化进程控制块链
for(int i = 0 ; i < pcb_num ; i++)
{
input_process(pcbc) ; //输入所有进程,并进入就绪队列
}
cout << "请选择进程调度算法:(1:优先数法,2:简单循环轮转法)" << endl;
int choose;
cin>>choose;
if(choose==1){
cout<<"执行优先数法"<<endl;
Priority(pcbc);
}
else if(choose==2){
cout<<"执行简单循环轮转法"<<endl;
TimeSlice(pcbc);
}
else
cout<<"选择错误"<<endl;
return 0;
}