(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
其中,进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。
指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。
要求运行时间——假设进程需要运行的单位时间数。
优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态——可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。
(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。
(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:
优先数-1
要求运行时间-1
来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。
(5) 进程运行一次后,若要求运行时间0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。
(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。
(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。
(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
下面开始数据结构的选取,因为这里只需要模拟进程的操作,所以只需要用一个PCB类对象就行。
需要具备进程名、运行时间、当前状态、优先数等属性,同时还需要开放给外界运行的接口以及判断是否退出的接口。
class PCB
{
public:
friend class List;
friend void PSA(List& q);
PCB(std::string processName, size_t time, size_t priority, size_t order)
: _processName(processName)
, _time(time)
, _priority(priority)
, _status('R')
, _order(order)
{}
//运行进程
void Run()
{
std::cout << "---进程" << _processName << "正在运行---" << std::endl;
//模拟运行,每运行一次优先数和剩余运行时间减一
--_priority;
--_time;
//运行时间已满,修改状态为结束
if (!_time)
{
_status = 'E';
}
std::cout << "进程名: " << _processName << " 优先级: " << _priority << " 剩余运行时间: " << _time << " 状态: " << _status << std::endl;
std::cout << "---进程" << _processName << "运行结束---" << std::endl;
std::cout << std::endl;
}
//判断当前状态是否结束
bool isEnd() const
{
return (_status == 'E');
}
private:
std::string _processName; //进程名
size_t _time; //运行时间
int _priority; //优先数
char _status; //状态
size_t _order; //顺序
};
同时,我采用C++ STL库中的链表来实现队列,为其重写了push函数,让他能够按照优先级插入队列
class List
{
public:
friend void PSA(List& q);
void Push(const PCB& data)
{
auto it = _list.begin();
while (it != _list.end())
{
//按照先后顺序以及优先级大小插入到合适的位置
if (data._priority > it->_priority || ((data._priority == it->_priority) && (data._order < it->_order)))
{
_list.insert(it, data);
return;
}
else
{
it++;
}
}
//如果比前面的都小就尾插
_list.push_back(data);
}
//输出表中所有进程信息
void Print() const
{
std::cout << "--------------------------------" << std::endl;
for (auto it = _list.begin(); it != _list.end(); it++)
{
std::cout << "进程名: " << it->_processName << " 优先级: " << it->_priority << " 剩余运行时间: " << it->_time << " 状态: " << it->_status << std::endl;
}
std::cout << "--------------------------------" << std::endl;
std::cout << std::endl;
}
private:
std::list<PCB> _list;
};
这个算法其实思路非常简单,每次只需要取出队首进行调度,如果调度结束后剩余运行时间为0则说明该进程运行结束,永久出队,如果不为0则说明还没运行完成,再次按优先级插入队列中即可,因为上面重写了Push函数,所以直接Push回去即可。如果队列为空,则说明所有的进程调度完毕。
void PSA(List& q)
{
while (!q._list.empty())
{
//取出队首运行
auto cur = q._list.front();
cur.Run();
q._list.pop_front();
//如果还没运行完则重新放入表中
if (!cur.isEnd())
{
q.Push(cur);
}
else
{
std::cout << "进程" << cur._processName << "运行结束, 退出" << std::endl;
}
q.Print();
}
std::cout << "************调度结束************" << std::endl;
}
#pragma
#include
#include
#include
class List;
class PCB
{
public:
friend class List;
friend void PSA(List& q);
PCB(std::string processName, size_t time, size_t priority, size_t order)
: _processName(processName)
, _time(time)
, _priority(priority)
, _status('R')
, _order(order)
{}
//运行进程
void Run()
{
std::cout << "---进程" << _processName << "正在运行---" << std::endl;
--_priority;
--_time;
if (!_time)
{
_status = 'E';
}
std::cout << "进程名: " << _processName << " 优先级: " << _priority << " 剩余运行时间: " << _time << " 状态: " << _status << std::endl;
std::cout << "---进程" << _processName << "运行结束---" << std::endl;
std::cout << std::endl;
}
//判断当前状态是否结束
bool isEnd() const
{
return (_status == 'E');
}
private:
std::string _processName; //进程名
size_t _time; //运行时间
int _priority; //优先数
char _status; //状态
size_t _order; //顺序
};
class List
{
public:
friend void PSA(List& q);
void Push(const PCB& data)
{
auto it = _list.begin();
while (it != _list.end())
{
//按照先后顺序以及优先级大小插入到合适的位置
if (data._priority > it->_priority || ((data._priority == it->_priority) && (data._order < it->_order)))
{
_list.insert(it, data);
return;
}
else
{
it++;
}
}
//如果比前面的都小就尾插
_list.push_back(data);
}
//输出表中所有进程信息
void Print() const
{
std::cout << "--------------------------------" << std::endl;
for (auto it = _list.begin(); it != _list.end(); it++)
{
std::cout << "进程名: " << it->_processName << " 优先级: " << it->_priority << " 剩余运行时间: " << it->_time << " 状态: " << it->_status << std::endl;
}
std::cout << "--------------------------------" << std::endl;
std::cout << std::endl;
}
private:
std::list<PCB> _list;
};
void PSA(List& q)
{
while (!q._list.empty())
{
//取出队首运行
auto cur = q._list.front();
cur.Run();
q._list.pop_front();
//如果还没运行完则重新放入表中
if (!cur.isEnd())
{
q.Push(cur);
}
else
{
std::cout << "进程" << cur._processName << "运行结束, 退出" << std::endl;
}
q.Print();
}
std::cout << "************调度结束************" << std::endl;
}
#include"PSA.hpp"
#include
using namespace std;
void test()
{
List List;
size_t pcbNum;
cout << "请输入进程的数量:" << endl;
cin >> pcbNum;
vector<string> processName(pcbNum);
vector<size_t> time(pcbNum);
vector<int> priority(pcbNum);
cout << "请输入所有进程的名字:" << endl;
for (size_t i = 0; i < pcbNum; i++)
{
cin >> processName[i];
}
for (size_t i = 0; i < pcbNum; i++)
{
cout << "请输入进程" << processName[i] << "的运行时间" << endl;
cin >> time[i];
cout << "请输入进程" << processName[i] << "的优先级" << endl;
cin >> priority[i];
PCB p(processName[i], time[i], priority[i], i);
List.Push(p);
}
List.Print();
PSA(List);
}
int main()
{
test();
}
这里直接用实验要求中的数据,五个进程,P1、P2、P3、P4、P5。
P1的要求运行时间为2,优先数为1。
P2的要求运行时间为3,优先数为5。
P3的要求运行时间为1,优先数为3。
P4的要求运行时间为2,优先数为4。
P5的要求运行时间为4,优先数为2。