实验目的】
在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。本实验模拟在单处理器情况下的处理器调度,帮助学生加深了解处理器调度的工作。
【实验内容】
选择一个调度算法,实现处理器调度。
【实验指导】
第一题:设计一个按优先数调度算法实现处理器调度的程序。
[ 提示] :
(1)假定系统有五个进程,每一个进程用一个进程控制块PCB 来代表,进程控制块的格式为:
进程名 |
指针 |
要求运行时间 |
优先数 |
状态 |
其中,进程名- 作为进程的标识,假设五个进程的进程名分别为P 1,P 2,P 3,P 4,P 5。
指针- 按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0” 。
要求运行时间- 假设进程需要运行的单位时间数。
优先数- 赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态- 可假设有两种状态,“ 就绪” 状态和“ 结束” 状态。五个进程的初始状态都为“ 就绪” ,用“R” 表示,当一个进程运行结束后,它的状态为“ 结束“ ,用”E“ 表示。
(2)在每次运行你所设计的处理器调度程序之前,为每个进程任意确定其“ 优先数” 和“ 要求运行时间” 。
(3)为了调度方便,把五个进程按给定的优先数从大到小连成队列用一单元指出队首进程,用指针指出队列的连接情况例:
队首标志
K 2
K 1 |
P 1 |
K 2 |
P 2 |
K 3 |
P 3 |
K 4 |
P 4 |
K 5 |
P 5 |
0 |
K 4 |
K 5 |
K 3 |
K 1 |
|||||
2 |
3 |
1 |
2 |
4 |
|||||
1 |
五 |
3 |
4 |
2 |
|||||
[R |
[R |
[R |
[R |
[R |
|||||
PCB1 |
PCB2 |
PCB3 |
PCB4 |
PCB5 |
(4)处理器调度总是选队首进程行。采用动态改变优先数的办法,进程每运行一次优先数就减“1” 。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:
优先数-1
要求运行时间-1
来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束在这里省去了这些工作。
(5)进程运行一次后,若要求运行时间≠ 0 ,则再将它加入队列;若要求运行时间= 0 ,则要把它的状态修改成“ 结束” (E ),且退出队列。
(6)若“ 就绪” 状态的进程队列不为空,则重复上面(4 )和(5 )的步骤,直到所有进程都成为“ 结束” 状态。
(7)在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。
(8)为五个进程任意确定一组“ 优先数” 和“ 要求运行时间” ,启动所设计的处理器调度程序,显示或打印逐次被选进程的进程名以及进程控制块的动态变化过程。
###############################################################################################
解:这个代码是用矢量数组来保存数据的,因为对指针掌握的不够熟练,所以就没有用指针另外这个程序不足的地方有很多......为什么不改呢,因为,不想改了..因为基本要求已经满足了,如果要再改的话,还不如尝试用更好的数据结构......而且能力有限,最近又很忙,在短时间内是不想改了,如果有能帮忙修改的同学,欢迎发到我的邮箱,必回〜
email:[email protected]
主要的错误在代码中的注释里已经添加上了,然后还有一个错误是,当still_have_time再减一等于零的时候,不打印show_every_time_running这个函数的内容,具体还是因为函数太乱,重灾区就在那两个打印的部分,如果有同学帮忙修改,真的是很感谢〜
(PS:发现csdn在google上对其支持特别不友好,因为google自带翻译,所以保存文章时就会自带html标签。。。)
另外,因为我啰嗦王的性格,我把打印弄的很详细,其实没必要这么麻烦,如果你想改的话〜废话不多说,上代码〜
experience_3_priority.h
//不会用指针。。。所以用vector存数据
#ifndef EXPERIENCE_3_PRIORITY_H_
#define EXPERIENCE_3_PRIORITY_H_
#include
#include
#include
#include
using namespace std;
int process_number = 5;
class PCB{
private:
//string process_name_;//想加个名字更好看来着,结果一想有点麻烦,就算了
int pid_;
int aim_run_time_;
int still_have_time_;
int priority_;
int state_;//1.waiting 2.running 3.exited
public:
PCB() = default;
//这里有两种方法,一种是进行拆分,将这一个set拆分为四个小set
//第二种方法就是用友元函数
//我选择的使用友元函数,毕竟c++,java的话可以用多个set get函数
void setPCB(int i, int t,int p,int st)
{
pid_ = i;
aim_run_time_ = t;
still_have_time_ = t;
priority_ = p;
state_ = st ;
}
string state_change()//因为数组里没法存不同类型的数据,所以这里做个切换
{
if(state_ == 1)
return "waiting";
if(state_ == 2)
return "running";
if(state_ == 3)
return "exited";
else
return 0;
}
void getPCB()
{
cout << left << setw(10) << pid_
<< setw(15) << aim_run_time_
<< setw(15) << still_have_time_
<< setw(10) << priority_
<< setw(7) << state_change() << endl;
}
friend bool compare_high(PCB v,PCB w);
friend void priority_scheduling(vector &init_queue,vector &wait_queue,int process_number);
friend void show_every_time_running(vector &init_queue);
};
void random_assign_value(vector &init_queue);
void getPCB_Introduction();
bool compare_high(PCB v,PCB w);
void sort_by_priority(vector &sort_high);
void show_every_time_running(vector &init_queue);
void show_after_running(const vector init_queue);
void priority_scheduling(vector &init_queue,vector &wait_queue,int process_number);
//因为函数实现在另一个文件中,所以下面的友元也要定义哦
bool compare_high(PCB v,PCB w);
void priority_scheduling(vector &init_queue,vector &wait_queue,int process_number);
void show_every_time_running(vector &init_queue);
#endif
#include"experience_3_priority.h"
int main(int argc, char const *argv[])
{
vector init_queue;
random_assign_value(init_queue);
sort_by_priority(init_queue);
cout << "The init queue is like this:\n";
getPCB_Introduction();
for(auto i : init_queue)
i.getPCB();
vector wait_queue = init_queue;
priority_scheduling(init_queue,wait_queue,process_number);
return 0;
}
void random_assign_value(vector &init_queue)
{
srand((unsigned int) time(NULL));//产生种子
for(int i = 1;i <= process_number;++i)
{
int priority_rand = 1+rand() % 10;//可以自行修改随机数所产生的范围
int run_time_rand = 1+rand() % 3;//注意random函数不是ANSI C标准,不能在gcc,vc等编译器下编译通过
PCB q;
q.setPCB(i,run_time_rand,priority_rand,1);
init_queue.push_back(q);
}
}
void getPCB_Introduction()
{
cout << left << setw(10) << "PID"
<< setw(15) << "AimRunTime"
<< setw(15) << "StillHaveTime"
<< setw(10) << "Priority"
<< setw(7) << "State" << endl;
}
bool compare_high(PCB v,PCB w)
{
if(v.priority_ == w.priority_) return v.pid_ < w.pid_;
return v.priority_ > w.priority_;
}
void sort_by_priority(vector &sort_high)
{
sort(sort_high.begin(),sort_high.end(),compare_high);
}
//这里是个小bug,因为在priority_scheduling中没处理好输出的问题
//所以这里就用另一个vector复制init_queue来进行输出,而middle_queue每一次调用完就被销毁了
void show_every_time_running(vector &init_queue)
{
vector middle_queue = init_queue;
cout << endl;
middle_queue[0].priority_ -= 1;
middle_queue[0].still_have_time_ -= 1;
if(middle_queue[0].still_have_time_ == 0)
middle_queue[0].state_ = 3;
else
{
middle_queue[0].state_ = 2;
cout << "This process is running:\n";
getPCB_Introduction();
middle_queue[0].getPCB();
}
}
void show_after_running(const vector init_queue)
{
cout << endl;
if(init_queue.size() == 0)
cout << "over!" << endl;
else
{
cout << "After this running,the waitqueue is like this:\n";
cout << endl;
getPCB_Introduction();
for(auto i : init_queue)
i.getPCB();
}
}
void priority_scheduling(vector &init_queue,vector &wait_queue,int process_number)
{
int process_number_now = process_number;
vector::iterator it;
it = init_queue.begin();
//调度
while(process_number_now)
{
show_every_time_running(init_queue);
wait_queue.erase(wait_queue.begin());
(*it).priority_ -= 1;
(*it).still_have_time_ -= 1;
if((*it).still_have_time_ == 0)//判断是否运行完
{
process_number_now -= 1;
(*it).state_ = 3;
show_after_running(init_queue);
init_queue.erase(init_queue.begin());//运行完了就初始队列也删去该进程
sort_by_priority(init_queue);
sort_by_priority(wait_queue);
}
else
{
(*it).state_ = 1;
wait_queue.push_back(*it);
sort_by_priority(init_queue);
sort_by_priority(wait_queue);
show_after_running(init_queue);
}
}
}
运行截图如图所示: