OS实验之处理机调度

弄了三天,有三点感想:
1.原来还是那么菜。稍微复杂一点的程序,类的设计,过程的控制,等等弄的焦头烂额的。不知道哪个年头能达到那些写linux源码,stl源码的人的水平。每天提醒自己一句,“设计模式摆在书桌上已经很久了!”
2.程序还是得天天练啊,数据结构很重要。双连表的建立,结点插入,删除及排序等操作的调试费了我大部分时间。不过数据结构设计好了,其他的代码是水到渠成,写的是酣畅淋漓。每天提醒自己一句,“你会眯着眼睛把各种排序算法写出来吗?”。
3.纸上得来终觉浅,实践才能有提高。这些天,基本上天天不是在看操作系统教材就是看linux内核分析的书,本以为写这样的程序是驾轻就熟的事了,但一入题分析,马上又得翻课本了,好失败。

1、实验题目
1) 设计一个按优先权调度算法实现处理机调度的程序;
2) 设计按时间片轮转算法实现处理机调度的程序。
2、要求
1) 可以随机输入若干进程,并按优先权排序(为了方便演示,排序单独写成一个函数来调用,实际在加入队列时就排序会更好些);
2) 从就绪队列的首选进程开始运行:优先权-1/要求运行时间-1,要求当运行时间=0时,撤销该进程;
3) 重新排序,进行下一轮调度;
4) 采用图形界面实现,可以适当加入动态动画效果;
5) 可以随时增加进程;
6) 规定道数,设置后备队列和挂起状态。若内存中进程少于规定道数,可以自动从后备队列(不在内存中吗?)调度一作业进入。被挂起进程进入挂起队列,设置解挂功能用于将指定挂起进程解挂并加入就绪队列。
7) 每次调度后,显示各进程的状态。

3.程序截图(mfc版)


4.源码
附上纯C++版的源码,后来根据实验要求又改了个mfc版本的,根据需要有些细节有出入。
pcglist.h,为进程链表结构

#ifndef PCBLIST_H
#define PCBLIST_H
#include 
< cstddef >

#define TASK_RESERVE  
0
#define TASK_READY      
1
#define TASK_RUNNING  
2
#define TASK_WAITE      
3
#define TASK_HANG      
4
#define TASK_OVER      
5
#define MAX_PID          
100
#define MAX_PRIO      
30
#define DEFAULT_TIME_SLICE 
10

typedef struct PCB
{
    
int pid;
    
int state;
    
int priority;    
    
int time_slice;    //要求运行时间
    int time_ran;    //已运行时间
    struct PCB* prep;
    struct PCB
* nextp;
    PCB():pid(
0),state(0),priority(0),time_slice(0),time_ran(0),prep(NULL),nextp(NULL){}
    bool run()
    
{
        
if( time_ran<time_slice )
        
{
            
if( priority>0 ) --priority;
            
++time_ran;
            state
=TASK_RUNNING;
            
return true;
        }

        
else
        
{
            state
=TASK_OVER;
            
return false;
        }

    }

}
Cpcb;

class Cpcblist
{
public:
    Cpcb
* head;
    Cpcb
* end;
public:
    
int count;
public:
    Cpcblist():count(
0){end=new Cpcb;head=end;}
    
void push_back(Cpcb*);
    
void insert_before(Cpcb* inpcb,Cpcb* nextpcb);
    Cpcb
* pop(Cpcb*);
    Cpcb
* pop_front();
    
void remove(Cpcb*);
    
//void swap(Cpcb*,Cpcb*);
    void sort();
    
~Cpcblist();
}
;
#endif
#include  " pcblist.h "

Cpcblist::
~ Cpcblist()
{
    Cpcb
* tp=head;
    Cpcb
* p=tp;
    
while( tp=tp->nextp )
    
{
        
delete p;
        p
=tp;
    }

}


void  Cpcblist::push_back(Cpcb *  p)
{
    
if( head==end )
    
{
        head
=p;
        p
->nextp=end;
        end
->prep=p;
    }

    
else
    
{
        p
->nextp=end;
        p
->prep=end->prep;
        end
->prep->nextp=p;
        end
->prep=p;
    }

    
++count;
}


void  Cpcblist::insert_before(Cpcb *  inpcb,Cpcb *  nextpcb)
{
    
if( head==nextpcb )
    
{
        inpcb
->nextp=head;
        inpcb
->prep=NULL;
        head
->prep=inpcb;
        head
=head->prep;
        
++count;
    }

    
else if( end==nextpcb )
            push_back(inpcb);
    
else
    
{
        inpcb
->nextp=nextpcb;
        inpcb
->prep=nextpcb->prep;
        nextpcb
->prep->nextp=inpcb;
        nextpcb
->prep=inpcb;
        
++count;
    }

}


Cpcb
*  Cpcblist::pop(Cpcb *  p)
{
    
if( p==head )
    
{
        head
=p->nextp;
        p
->nextp->prep=NULL;
    }

    
else
    
{
        p
->prep->nextp=p->nextp;
        p
->nextp->prep=p->prep;
    }

    p
->prep=p->nextp=NULL;
    
--count;
    
return p;
}


Cpcb
*  Cpcblist::pop_front()
{
    
return pop(head);
}


void  Cpcblist::remove(Cpcb *  p)
{
    pop(p);
    
delete p;
}


// 直接插入排序以减少排序次数
void  Cpcblist::sort()
{
    Cpcb
* ap;
    Cpcb
* bp=head;
    Cpcb
* tp;
    
while( bp!=end && bp->nextp!=end )
    
{
        ap
=bp->nextp;
        
if( ap->priority>bp->priority && ap!=end )
        
{
            
//if:如果ap的优先级比头结点还大就直接插在头部
            //else:判断插入位置,并插入
            if( head->priority<ap->priority ) 
            
{
                pop(ap);
                insert_before(ap,head);    
            }

            
else
            
{
                tp
=bp->prep;
                
while( tp->priority<ap->priority && tp!=head )
                    tp
=tp->prep;
                pop(ap);
                insert_before(ap,tp
->nextp);
            }

        }

        
else
            bp
=bp->nextp;
    }

}
shd.h,包含进程队列信息
#ifndef SHD_H
#define SHD_H
#include 
" pcblist.h "

#define SCHED_PRIO    
0
#define SCHED_RR      
1

class Crunqueue
{
public:
    Cpcblist reserve;  
//后备队列
    Cpcblist active;    //活动进程队列
    Cpcblist hang;        //挂起进程队列
    Cpcblist over;        //完成进程队列
    Cpcb* current;  //当前运行的进程

private:
    Cpcb
* randpcb(); 
    
void add_to_reserve(Cpcb* p);
    
void add_to_reday(Cpcb* p);
    
void add_to_hang(Cpcb* p);
    
void active_hang(Cpcb* p);
    
void add_to_over(Cpcb* p);
    
void out_schedule_prio();
    
void out_schedule_rr();

    
void in_schedule();
    
void in_schedule_prio();
    
void in_schedule_rr();

private:
    
int sched_kind;    //调度方式,默认为优先级调度
public:
    
int n_max_run;    //规定就绪队列的最大进程数目
    int n_process;    //全部进程数目
public:
    Crunqueue(
int n=10);
    
void out_schedule();
    
void run(int kind=0);
}
;
#endif
shd.cpp
#include  " shd.h "
#include 
< iostream >
#include 
< iomanip >      // for setw()
#include  < cstdlib >      // for srand() and rand()
#include  < cassert >
#define ALL_PROCESS 
10
using namespace std;

Crunqueue::Crunqueue(
int  n):n_max_run(n),n_process( 0 ),sched_kind( 0 )
{
    
for(int i=0;i<ALL_PROCESS;i++)
    
{
        Cpcb
* p=randpcb();
        p
->pid=i;
        add_to_reserve(p);
    }

}


Cpcb
*  Crunqueue::randpcb()
{
    
++n_process;
    srand(n_process);
    Cpcb
* p=new Cpcb;
    p
->pid=n_process;
    p
->priority=rand()%MAX_PRIO;
    p
->time_slice=(int)rand()%DEFAULT_TIME_SLICE+1;
    
return p;
}


void  Crunqueue::add_to_reserve(Cpcb *  p)
{
    
if( p->state!=TASK_OVER )
    
{
        reserve.push_back(p);
        p
->state=TASK_RESERVE;
    }

}


void  Crunqueue::add_to_reday(Cpcb *  p)
{
    
if( active.count<n_max_run )
    
{
        
if( p->state!=TASK_READY )
            p
->state=TASK_READY;
        active.push_back(p);
    }

}


void  Crunqueue::add_to_hang(Cpcb *  p)
{
    
if( p->state==TASK_HANG || p->state==TASK_OVER )
        
return;
    
if( p )
    
{
        active.pop(p);    
        hang.push_back(p);
        p
->state=TASK_HANG;
    }

    schedule();
}


void  Crunqueue::active_hang(Cpcb *  p)
{
    
if( p->state==TASK_HANG )
    
{
        hang.pop(p);
        active.push_back(p);
        in_schedule();
    }

}


void  Crunqueue::add_to_over(Cpcb *  p)
{
    over.push_back(p);
    p
->state=TASK_OVER;
    out_schedule();
}


/*按优先级调度--没有采用搜索最高优先级,而用排序是为了与多处理机兼容^_^)*/
void  Crunqueue::out_schedule_prio()
{
    reserve.sort();
    out_schedule_rr();
}


void  Crunqueue::out_schedule_rr()
{
    
int canrun;
    
//判断后备队列是否超出规定运行线程数,是则按规定道数慢慢来,否则全部上
    if( reserve.count>n_max_run-active.count) canrun=n_max_run;
    
else canrun=reserve.count+active.count;
    
for(int i=active.count;i<canrun;i++)
    
{
        add_to_reday(reserve.pop_front());
    }

}


void  Crunqueue::in_schedule_prio()
{
    active.sort();
    
if!active.head->run() )
    
{
        Cpcb
* p=active.pop_front();    
        add_to_over(p);
    }

    out_schedule();
}


void  Crunqueue::in_schedule_rr()
{
    
while( active.head->run() );    //一直运行,直到该进程结束
    Cpcb* p=active.pop_front();    
    add_to_over(p);
    
if!active.count && !hang.count ) return;
    out_schedule();    
//重新载入进程
}


/*内调度(俗语低级调度或进程调度):负责就绪队列中进程切换*/
void  Crunqueue::in_schedule()
{
    
if( active.count==0 ) return;
    
if( SCHED_PRIO==sched_kind )
        in_schedule_prio();
    
else if( SCHED_RR==sched_kind )
        in_schedule_rr();
}


/*外调度(俗语高级调度或作业调度):负责就绪队列线程的供给*/
void  Crunqueue::out_schedule()
{
    
if( reserve.count>0 )
    
{
        
if( SCHED_PRIO==sched_kind )
            out_schedule_prio();
        
else if( SCHED_RR==sched_kind )
            out_schedule_rr();
        
else    
            
return;
    }

    
/*外调度是为内调度作准备,循环机制*/
    
if( active.count || hang.count )
        in_schedule();
}


/*启动调度模拟*/
void  Crunqueue::run( int  kind)
{
    sched_kind
=kind;
    out_schedule();
}


ostream
&  operator << (ostream &  os,const Cpcb &  p)
{
    os
<<setw(4)<<p.pid
        
<<setw(10)<<p.priority
        
<<setw(12)<<p.time_slice
        
<<setw(12)<<p.time_ran;
    
switch(p.state)
    
{
    
case 0:os<<setw(10)<<"reserve"<<endl;break;
    
case 1:os<<setw(10)<<"reday"<<endl;break;
    
case 2:os<<setw(10)<<"running"<<endl;break;
    
case 3:os<<setw(10)<<"waite"<<endl;break;
    
case 4:os<<setw(10)<<"hang"<<endl;break;
    
case 5:os<<setw(10)<<"over"<<endl;break;
    
default:os<<setw(10)<<"unknown"<<endl;
    }

    
return os;
}


ostream
&  operator << (ostream &  os,const Cpcblist &  pl)
{
    
//if( sched_kind==SCHED_PRIO )
    //    cout<<"priotity schedul"<<endl;
    //else if( sched_kind==SCHED_RR )
    //    cout<<"RR schedul"<<endl;
    if( pl.count>0 )
    
{
        os
<<setw(4)<<"pid"
        
<<setw(10)<<"priority"
        
<<setw(12)<<"time slice"
        
<<setw(12)<<"time ran"
        
<<setw(10)<<"state"<<endl;
        
char oldfill=os.fill('-');
        os
<<setw(48)<<'-'<<endl;
        os.fill(oldfill);
        
for(Cpcb* p=pl.head;p!=pl.end;p=p->nextp)
            os
<<*p;
        os
<<endl;
    }

    
return os;
}


int  main()
{
    Crunqueue shd(
4);
    
//shd.reserve.sort();
    cout<<shd.reserve;
    shd.run(
0);
    cout
<<shd.over;
    
int i;
    cin
>>i;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值