cpp
复制代码
#include <iostream>
#include <queue>
using namespace std;
//进程三种状态,这里增加一种,表示虽然输入,但是还没有到达进入系统时刻typedef enum ProcessState{Executing, Ready, Finish, Unarrive}STATE;
typedef struct process_pcb
{
int ID; //进程标识
int priority; //进程优先数,值越大,优先级越高
int arrive_time; //进程到达时间,以时间片为单位
int service_time; //进程需要总的服务时间
int start_time; //进程开始执行时间
int end_time; //进程结束时间
int all_time; //进程仍然需要运行时间
int cpu_time; //进程已占用cpu时间
const char* state; //进程状态
}PCB;
//用于打印进程三种状态
const char* StateString[] = {"Executing", "Ready", "Finish", "--"};
//排序比较函数:按照进程到达时间升序排列
bool cmp_arrive_time(const PCB a, const PCB b);
//排序比较函数:按照进程优先数降序排序
bool cmp_priority(const PCB a, const PCB b);
void input_process(); //输入进程信息
int select_policy(); //选择进程调度策略
void print_all(int current); //打印所有进程信息
void FCFS(); //先来先服务算法
void round_robin(); //时间片轮转算法
void dynamic_prio(); //动态优先级算法
PCB* running_process = NULL;//当前运行任务
//进程到达队列,如进程还没到到达时间,则该进程仍然在到达队列中
vector<PCB> arrive_queue;
vector<PCB> ready_queue;//就绪队列
vector<PCB> finish_queue;//完成队列
int main()
{
printf("===================================================\n");
printf(" 操作系统进程调度模拟实验 \n");
printf("===================================================\n");
printf("\n");
input_process();
print_all(-1); //打印进程的初始状态
int policy = select_policy();
switch (policy)
{
case 1:
FCFS();
break;
case 2:
round_robin();
break;
case 3:
dynamic_prio();
break;
default:
FCFS();
break;
}
}
//按进程到达时间升序排列,先到达的排在队首
bool cmp_arrive_time(const PCB a, const PCB b)
{
return a.arrive_time < b.arrive_time;
}
//按进程优先级降序排列,优先级高的排在队首
//如优先级相同,先到的进程排在前面
bool cmp_priority(const PCB a, const PCB b)
{
if (a.priority != b.priority) {
return a.priority > b.priority;
}
else {
return a.arrive_time < b.arrive_time;
}
}
//选择进程调度策略
int select_policy()
{
printf("\n请选择调度算法(输入序号选择):\n");
printf("1.先来先服务调度(FCFS) \n");
printf("2.时间片轮转调度(Round-Robin) \n");
printf("3.动态优先级调度(DynamicPriority) \n");
int n;
printf("请输入调度算法序号:");
while (scanf_s("%d", &n)) {
if (n > 3 || n < 1) {
printf("对不起,输入有误,请重新输入!\n");
}
else {
break;
}
}
return n;
}
//输入进程信息
void input_process()
{
int num;
printf("请输入进程数量:");
scanf_s("%d", &num);
PCB pro;
for (int i = 1; i <= num; i++) {
printf("\n请输入第%d个进程的到达时间、服务时间及优先级(以空格隔开):\n", i);
scanf_s("%d%d%d", &pro.arrive_time, &pro.service_time, &pro.priority);
pro.ID = i;
pro.all_time = pro.service_time;
pro.cpu_time = 0;
pro.start_time = -1;//开始时间、结束时间默认为-1,表示尚未被调度过
pro.end_time = -1;
pro.state = "Unarrive";//初始化为尚未进入到达
arrive_queue.push_back(pro);
}
//按照到达时间升序排队
sort(arrive_queue.begin(), arrive_queue.end(), cmp_arrive_time);
}
//打印单个进程的信息
void print_process(PCB* pro)
{
if (pro == NULL) {
return;
}
printf("%4d%10d%10d%8d%10s", pro->ID, pro->arrive_time, pro->service_time, pro->priority, pro->state);
if (pro->start_time == -1) {//开始时间,结束时间,剩余时间
printf("%10s%10s%10s", "--", "--", "--");
}
else {
if (pro->end_time == -1) {
printf("%10d%10s%10d", pro->start_time, "--", pro->all_time);
}
else {
printf("%10d%10d%10d", pro->start_time, pro->end_time, pro->all_time);
}
}
if (pro->state == "Finish")//周转时间及带权周转时间
{
printf("%10d%10.2lf\n", pro->end_time - pro->arrive_time, (float)(pro->end_time - pro->arrive_time) / (float)pro->service_time);
}
else {
printf("%10s%10s\n", "--", "--");
}
}
//打印所有进程的信息
void print_all(int current)
{
if (current == -1) {
printf("\n进程初始状态:%d\n", current);
}
else {
printf("\n当前时刻为:%d\n", current);
}
printf("进程号 到达时间 服务时间 优先级 状态 开始时间 结束时间 剩余时间 周转时间 带权周转时间\n");
//首先打印正在运行的进程
if (running_process != NULL) {
print_process(running_process);
}
vector<PCB>::iterator it;
//然后打印就绪队列中的进程
for (it = ready_queue.begin(); it != ready_queue.end(); it++) {
print_process(&(*it));
}
//然后打印完成队列中的进程
for (it = finish_queue.begin(); it != finish_queue.end(); it++) {
print_process(&(*it));
}
//然后打印仍然在到达队列中的进程
for (it = arrive_queue.begin(); it != arrive_queue.end(); it++) {
print_process(&(*it));
}
}
//先来先服务算法
void FCFS()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while (1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if (!running_process && arrive_queue.empty() && ready_queue.empty()) {
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while (!arrive_queue.empty()) {
PCB pro = arrive_queue[0];
if (pro.arrive_time <= chip) {
pro.state = "Ready";
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}
else {
break;
}
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if (need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
running_process->start_time = chip;
running_process->state = "Executing";
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//FCFS当前任务运行到结束,才可能调度下一个任务
if (running_process) {
running_process->end_time = running_process->start_time + running_process->service_time;
running_process->state = "Finish";
running_process->cpu_time = running_process->service_time;
running_process->all_time = 0;
chip += running_process->service_time;
finish_queue.push_back(*running_process);//将完成任务放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {
chip += 1;
}
}
//所有任务全部完成后,打印一次
print_all(chip);
}
//时间片轮转算法
void round_robin()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while (1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if (!running_process && arrive_queue.empty() && ready_queue.empty()) {
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while (!arrive_queue.empty()) {
PCB pro = arrive_queue[0];
if (pro.arrive_time <= chip) {
pro.state = "Ready";
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}
else {
break;
}
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if (need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
if (running_process->start_time == -1) {//首次运行
running_process->start_time = chip;
}
running_process->state = "Executing";
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//当前运行任务完成个时间片,判断该任务是否已经完成
if (running_process) {
running_process->cpu_time += 1;
running_process->all_time -= 1;
if (running_process->all_time == 0) {//任务运行结束
running_process->end_time = chip + 1;
running_process->state = "Finish";
finish_queue.push_back(*running_process);//将其放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {//任务没有完成,如果就绪队列中仍有任务,则轮转调度,否则不调度(这里是一种调度的优化,避免重新调度开销)
if (!ready_queue.empty()) {
running_process->state = "Ready";
ready_queue.push_back(*running_process);//将其放回就绪队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {
need_schedule = false;
}
}
}
chip += 1;
}
//所有任务全部完成后,打印一次
print_all(chip);
}
// 动态优先级算法
void dynamic_prio()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while (1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if (!running_process && arrive_queue.empty() && ready_queue.empty()) {
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while (!arrive_queue.empty()) {
PCB pro = arrive_queue[0];
if (pro.arrive_time <= chip) {
pro.state = "Ready";
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}
else {
break;
}
}
if (!ready_queue.empty()) {
//将就绪进程按照优先级降序排列
sort(ready_queue.begin(), ready_queue.end(), cmp_priority);
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if (need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
if (running_process->start_time == -1) {//首次运行
running_process->start_time = chip;
}
running_process->state = "Executing";
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//当前运行任务完成个时间片,判断该任务是否已经完成
if (running_process) {
running_process->cpu_time += 1;
running_process->all_time -= 1;
if (running_process->all_time == 0) {//任务运行结束
running_process->end_time = chip + 1;
running_process->state = "Finish";
finish_queue.push_back(*running_process);//将其放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {//任务没有完成,如果就绪队列中仍有任务,且优先级大于或等于本任务的优先级,则轮转调度,否则不调度
if (running_process->priority > 1) {
running_process->priority -= 1;//优先级最小为1
}
if (!ready_queue.empty() && ready_queue[0].priority >= running_process->priority) {
running_process->state = "Ready";
ready_queue.push_back(*running_process);//将其放回就绪队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {
need_schedule = false;
}
}
}
chip += 1;
}
//所有任务全部完成后,打印一次
print_all(chip);
}