使用C和C++实现的简单的操作系统进程调度算法
1.使用的数据结构
//PCB数据结构
struct PCB{
long id;
int priority=1;
long start;
long runtime;
long usedtime;
long end;
void create(long i,long st,long rt){
id=i;
start=st;
runtime=rt;
}
void selected(long now){
printf("(%02d:%02d) select process %d,need:%-3d,used:%-3d\n",now/60,now%60,id,runtime,usedtime);
}
void run(long now){
//printf("(%02d:%02d) process %d run,need:%-3d,used:%-3d++\n",now/60,now%60,id,runtime,usedtime);
usedtime++;
}
}P[10010];
2.构造测试用例
//构建测试用例
map<long,long> mp;
void initPCS(){
//默认
long start[6]={0,8*60,8*60+20,8*60+25,8*60+30,8*60+35};
long runtimes[6]={0,25,10,20,20,15};
memset(P,0,5*sizeof(PCB));
for(long id=1;id<=5;id++){
P[id].create(id,start[id],runtimes[id]);
mp[ start[id] ]=id;
}
}
3.先来先服务
3.1流程
3.2代码实现
//FCFS算法
void FCFS(){
long now=8*60;//定义初始时间 08:00
const long end=12*60;//定义终止时间 12:00
queue<int> wait;//等待队列
long id;//运行进程的ID
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
long id=mp[now];
wait.push(id);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
id=wait.front();//选出先来的(队头)
wait.pop();
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
continue;
}
}
}
3.3运行结果
4.短作业优先算法
4.1流程
短作业优先与先来先服务唯一的不同在于:短作业优先在选择作业时需要去作业中寻找最短者
4.2代码实现
//SJF算法(非抢占式)
void SJF(){
long now=8*60;//定义初始时间
const long end=12*60;//定义终止时间
long id;//运行进程的ID
vector<int> wait;//等待队列
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
//找到最短的进程
long surplus=(1<<16);
int itmp;
for(int i=0;i<wait.size();i++){
long s=P[ wait[i] ].runtime;
if(s<surplus){
surplus=s;
itmp=i;
}
}
id=wait[itmp];
wait.erase(wait.begin()+itmp);
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
continue;
}
}
}
4.3运行结果
5高相应比优先算法
5.1代码实现
void HRRN(){
long now=8*60;//定义初始时间
const long end=12*60;//定义终止时间
long id;//运行进程的ID
vector<int> wait;//等待队列
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
//找到高响应比的进程
double surplus=0;
int itmp;
for(int i=0;i<wait.size();i++){
double s=1+((now-P[ wait[i] ].start)-P[ wait[i] ].usedtime)*1.0/P[ wait[i] ].runtime;//相应比=1+等待时间/要求服务时间
if(s>surplus){
surplus=s;
itmp=i;
}
}
id=wait[itmp];
wait.erase(wait.begin()+itmp);
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
continue;
}
}
}
5.2运行结果
6.轮转算法
6.1流程
轮转算法是在FCFS的基础上加上了时间片的限制
6.2代码实现
//RR算法
void RR(){
long now=8*60;//定义初始时间 08:00
const long end=12*60;//定义终止时间 12:00
const long dt=10;//时间片长度
queue<int> wait;//等待队列
long id;//运行进程的ID
if(mp.find(now)!=mp.end()){//有进程创建
long id=mp[now];
wait.push(id);//放入wait队列
}
while(now<end){
if(wait.size()==0){//等待队列为空
//cout<<"jump"<<endl;
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
continue;
}
id=wait.front();//选出先来的(队头)
wait.pop();
P[id].selected(now);
for(long i=0;i<dt;i++){
P[id].run(now++);
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
if(P[id].runtime!=P[id].usedtime){//运行未结束
//wait.push(id);
}else{//运行结束
P[id].end=now;
break;
}
}
if(P[id].runtime!=P[id].usedtime){//运行未结束
wait.push(id);
}
}
}
6.3运行结果
7.抢占式SJF
7.1流程
7.2代码实现
//SJF算法(抢占式)
void SJF2(){
long now=8*60;//定义初始时间
const long end=12*60;//定义终止时间
long id;//运行进程的ID
vector<int> wait;//等待队列
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
status=0;//当前进程终止运行
if(P[id].runtime!=P[id].usedtime)
wait.push_back(id);//当前进程放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
//找到最短的进程
long surplus=(1<<16);
int itmp;
for(int i=0;i<wait.size();i++){
long s=P[ wait[i] ].runtime-P[ wait[i] ].usedtime;
if(s<surplus){
surplus=s;
itmp=i;
}
}
id=wait[itmp];
wait.erase(wait.begin()+itmp);
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
continue;
}
}
}
7.3运行结果
8.数据打印方法
//数据统计
void cacu_data(int n){
double sumt1=0;
double sumt2=0;
printf("---------------------------------------------------\n");
printf("%2s|%8s|%8s|%8s|%8s|%12s\n","ID","到达时间","运行时间",
"完成时间","周转时间","带权周转时间");
for(int i=1;i<=n;i++){
printf("%-2d|(%02d:%02d) |%-4d min|(%02d:%02d) |%-4d min|%-4lf\n",P[i].id,
P[i].start/60,P[i].start%60,P[i].runtime,P[i].end/60,P[i].end%60,
P[i].end-P[i].start,(P[i].end-P[i].start)*1.0/P[i].runtime);
sumt1+=P[i].end-P[i].start;
sumt2+=(P[i].end-P[i].start)*1.0/P[i].runtime;
}
cout<<"平均周转时间:"<<sumt1/n<<endl;
cout<<"平均带权周转时间:"<<sumt2/n<<endl;
}
9.完整代码
#include<iostream>
#include<stdio.h>
#include<queue>
#include<vector>
#include<cstring>
#include<map>
using namespace std;
//PCB数据结构
struct PCB{
long id;
int priority=1;
long start;
long runtime;
long usedtime;
long end;
void create(long i,long st,long rt){
id=i;
start=st;
runtime=rt;
}
void selected(long now){
printf("(%02d:%02d) select process %d,need:%-3d,used:%-3d\n",now/60,now%60,id,runtime,usedtime);
}
void run(long now){
//printf("(%02d:%02d) process %d run,need:%-3d,used:%-3d++\n",now/60,now%60,id,runtime,usedtime);
usedtime++;
}
}P[10010];
map<long,long> mp;
//构建测试用例
void initPCS(){
//默认
long start[6]={0,8*60,8*60+20,8*60+25,8*60+30,8*60+35};
long runtimes[6]={0,25,10,20,20,15};
memset(P,0,5*sizeof(PCB));
for(long id=1;id<=5;id++){
P[id].create(id,start[id],runtimes[id]);
mp[ start[id] ]=id;
}
}
//FCFS算法
void FCFS(){
long now=8*60;//定义初始时间 08:00
const long end=12*60;//定义终止时间 12:00
queue<int> wait;//等待队列
long id;//运行进程的ID
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
long id=mp[now];
wait.push(id);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
id=wait.front();//选出先来的(队头)
wait.pop();
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
continue;
}
}
}
//SJF算法(非抢占式)
void SJF(){
long now=8*60;//定义初始时间
const long end=12*60;//定义终止时间
long id;//运行进程的ID
vector<int> wait;//等待队列
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
//找到最短的进程
long surplus=(1<<16);
int itmp;
for(int i=0;i<wait.size();i++){
long s=P[ wait[i] ].runtime;
if(s<surplus){
surplus=s;
itmp=i;
}
}
id=wait[itmp];
wait.erase(wait.begin()+itmp);
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
continue;
}
}
}
//SJF算法(抢占式)
void SJF2(){
long now=8*60;//定义初始时间
const long end=12*60;//定义终止时间
long id;//运行进程的ID
vector<int> wait;//等待队列
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
status=0;//当前进程终止运行
if(P[id].runtime!=P[id].usedtime)
wait.push_back(id);//当前进程放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
//找到最短的进程
long surplus=(1<<16);
int itmp;
for(int i=0;i<wait.size();i++){
long s=P[ wait[i] ].runtime-P[ wait[i] ].usedtime;
if(s<surplus){
surplus=s;
itmp=i;
}
}
id=wait[itmp];
wait.erase(wait.begin()+itmp);
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
continue;
}
}
}
void HRRN(){
long now=8*60;//定义初始时间
const long end=12*60;//定义终止时间
long id;//运行进程的ID
vector<int> wait;//等待队列
bool status=0;//运行进程的状态(0:结束)
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
while(now<end){
if(status){//进程尚未运行结束
P[id].run(now);
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
if(P[id].runtime==P[id].usedtime){//运行结束
P[id].end=now;
status=0;//运行状态修改为:运行结束
}
continue;
}
if(wait.size()!=0){
//找到高响应比的进程
double surplus=0;
int itmp;
for(int i=0;i<wait.size();i++){
double s=1+((now-P[ wait[i] ].start)-P[ wait[i] ].usedtime)*1.0/P[ wait[i] ].runtime;//相应比=1+等待时间/要求服务时间
if(s>surplus){
surplus=s;
itmp=i;
}
}
id=wait[itmp];
wait.erase(wait.begin()+itmp);
status=1;//运行状态修改为:运行中
P[id].selected(now);//打印日志
}else{
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push_back(mp[now]);//放入wait队列
}
continue;
}
}
}
//RR算法
void RR(){
long now=8*60;//定义初始时间 08:00
const long end=12*60;//定义终止时间 12:00
const long dt=10;//时间片长度
queue<int> wait;//等待队列
long id;//运行进程的ID
if(mp.find(now)!=mp.end()){//有进程创建
long id=mp[now];
wait.push(id);//放入wait队列
}
while(now<end){
if(wait.size()==0){//等待队列为空
//cout<<"jump"<<endl;
now++;
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
continue;
}
id=wait.front();//选出先来的(队头)
wait.pop();
P[id].selected(now);
for(long i=0;i<dt;i++){
P[id].run(now++);
if(mp.find(now)!=mp.end()){//有进程创建
wait.push(mp[now]);//放入wait队列
}
if(P[id].runtime!=P[id].usedtime){//运行未结束
//wait.push(id);
}else{//运行结束
P[id].end=now;
break;
}
}
if(P[id].runtime!=P[id].usedtime){//运行未结束
wait.push(id);
}
}
}
//数据统计
void cacu_data(int n){
cout<<endl<<"------初始数据------"<<endl;
printf("%-2s|%-8s|%-8s\n","ID","到达时间","运行时间");
for(int i=1;i<=n;i++){
printf("%-2d|(%02d:%02d) |%-4d min\n",
P[i].id,
P[i].start/60,P[i].start%60,P[i].runtime);
}
double sumt1=0;
double sumt2=0;
printf("\n----------结果统计---------------------------------\n");
printf("%2s|%8s|%8s|%8s|%8s|%12s\n","ID","到达时间","运行时间",
"完成时间","周转时间","带权周转时间");
for(int i=1;i<=n;i++){
printf("%-2d|(%02d:%02d) |%-4d min|(%02d:%02d) |%-4d min|%-4lf\n",P[i].id,
P[i].start/60,P[i].start%60,P[i].runtime,P[i].end/60,P[i].end%60,
P[i].end-P[i].start,(P[i].end-P[i].start)*1.0/P[i].runtime);
sumt1+=P[i].end-P[i].start;
sumt2+=(P[i].end-P[i].start)*1.0/P[i].runtime;
}
cout<<"平均周转时间:"<<sumt1/n<<endl;
cout<<"平均带权周转时间:"<<sumt2/n<<endl;
}
//主函数
int main(){
initPCS();
//FCFS();//先来先服务
//SJF();//短作业优先
//SJF2();//抢占式短作业优先
//HRRN();//高相应比优先
RR();//轮转(时间片默认10分钟)
cacu_data(5);//统计
return 0;
}