题目
请编写一个程序,模拟若干进程调度执行的情况。假设进程的状态分为执行和就绪两种。
每个进程以其PCB为代表即可,无需创建真正的进程。
以链表的方式组织PCB,分为三个队列:
freeQueue:一个空白PCB队列
readyQueue:一个就绪队列
runningQueue:一个执行队列
程序开始运行时,用户输入进程数量n,以及每个进程需要运行的时间t0/t1/…/tn。
程序从空白PCB队列中取出PCB创建进程,插入readyQueue。
进程的调度采用随机的方式,即从就绪队列中随机选择一个进程投入运行(就是将该PCB中的状态变量赋值为“运行”)。相应的修改其所在队列,并且原来处于运行态的进程需要转变为“就绪”态,插入readyQueue。
假设时间片是2,进程每次调度运行后,其还需运行的时间应该减少2,直至为0,即表示该进程执行完毕。需要回收PCB到freeQueue。
每次发生调度的时候,需要打印信息示例:
Sched: P0(Running -> Ready), P3(Ready -> Running)
Running: P3
Ready: P1->P2->P0
上述信息表示调度时P0处于运行态,选择P3运行,P0进程的PCB进入就绪队列,并且在队尾。就绪队列是按照队列节点次序输出进程名称。
示例片段代码:
#define free 0
#define ready 1
#define running 2
#define ts 2 /* time slice /
struct PCB {
int pid; / 进程ID /
int pstate; / 进程状态 */
char pname; / 映象名称 /
int ptime; / 剩余运行时间 */
struct PCB pnext; / 下一个PCB */
}
代码
//
// Created by Jintao on 2019/12/14.
//
// 题目:
// 请编写一个程序,模拟若干进程调度执行的情况。假设进程的状态分为执行和就绪两种。
// 每个进程以其PCB为代表即可,无需创建真正的进程。以链表的方式组织PCB,分为三个队列:
// freeQueue:一个空白PCB队列
// readyQueue:一个就绪队列
// runningQueue:一个执行队列
//
// 程序开始运行时,用户输入进程数量n,以及每个进程需要运行的时间t0/t1/…/tn。
// 程序从空白PCB队列中取出PCB创建进程,插入readyQueue。
//
// 进程的调度采用随机的方式,即从就绪队列中随机选择一个进程投入运行(就是将该PCB中的状态变量赋值为“运行”)。
// 相应的修改其所在队列,并且原来处于运行态的进程需要转变为“就绪”态,插入readyQueue。
// 假设时间片是2,进程每次调度运行后,其还需运行的时间应该减少2,直至为0,即表示该进程执行完毕。需要回收PCB到freeQueue。
// 每次发生调度的时候,需要打印信息示例:
//
// Sched: P0(Running -> Ready), P3(Ready -> Running)
// Running: P3
// Ready: P1->P2->P0
//
// 上述信息表示调度时P0处于运行态,选择P3运行,P0进程的PCB进入就绪队列,并且在队尾。就绪队列是按照队列节点次序输出进程名称。
#include <cstring>
#include<cstdio>
#include<cstdlib>
#include<ctime>
const int timeSlice = 2; // 时间片
/// 进程状态 枚举
enum struct PState {
free, ready, running
};
struct PCB {
int pid; // 进程id
PState pstate; // 进程状态
char name[20]; // 进程名称 P0, P1, P2...
int time; // 剩余运行时间
PCB *next; // 下一个PCB
PCB() : next(nullptr) {}
PCB(int pid, PState pstate, char *name, int time, PCB *next) :
pid(pid), pstate(pstate), time(time), next(next) {
strcpy(this->name, name);
}
};
/// PCB链表
struct PCBList {
PCB *head;
int length;
PCBList() : length(0) {
head = new PCB;
}
~PCBList() {
__freeAllPCB();
delete head;
}
/// 加在链表的首部
void push(PCB *pPcb) {
pPcb->next = head->next;
head->next = pPcb;
length += 1;
}
/// 随机pop一个PCB
PCB *randPop();
bool empty() {
return length == 0;
}
void printList();
/// 释放PCB资源,不包括head
void __freeAllPCB();
};
/// 记录PCB调用信息
struct PCBSched {
PCB *pcb;
PState from;
PState to;
/// 获取PCB调用信息
char *getInfo(char *dest);
PCBSched() = default;
PCBSched(PCB *pcb, PState from, PState to) : pcb(pcb), from(from), to(to) {}
} pcbSched[2];
PCBList freeList;
PCBList readyList;
PCBList runningList;
/// 初始化readyList, 理论最大进程数
int initReadyList();
/// 进程调度
void schedule();
/// 打印信息
void printInfo();
int main() {
srand(time(nullptr));
initReadyList();
// A'+B' = (AB)'
while (!(runningList.empty() && readyList.empty())) {
schedule();
printInfo();
}
}
PCB *PCBList::randPop() {
int randNum = rand() % length;
// get *randPCB
PCB *pPcb = head->next, *pPrev = head; // pPrev 记录 前一个pPcb的值
while (randNum--) {
pPrev = pPcb;
pPcb = pPcb->next;
}
// pop pPcb
PCB *pOld = pPcb; // 存储 要pop返回的PCB
pPrev->next = pPcb->next;
length -= 1;
return pOld;
}
void PCBList::printList() {
if (!length) {
printf("\n");
return;
}
PCB *pPcb = head->next;
while (pPcb->next != nullptr) {
printf("%s(%d)->", pPcb->name, pPcb->time);
pPcb = pPcb->next;
}
printf("%s(%d)\n", pPcb->name, pPcb->time);
}
void PCBList::__freeAllPCB() {
PCB *pPcb = head->next;
PCB *pOld;
while (length--) {
pOld = pPcb;
pPcb = pPcb->next;
delete pOld;
}
}
char *__pStateToStr(char *dest, PState pState);
char *PCBSched::getInfo(char *dest) {
char pStateTemp[2][10];
sprintf(dest, "%s(%s -> %s)", pcb->name, __pStateToStr(pStateTemp[0], from),
__pStateToStr(pStateTemp[1], to));
return dest;
}
int initReadyList() {
int procNum; // 进程数量
scanf("%d", &procNum);
for (int i = 0; i < procNum; i++) {
char name[20];
sprintf(name, "P%d", i);
int pTime;
scanf("%d", &pTime);
readyList.push(new PCB(i, PState::ready, \
name, pTime, nullptr));
}
return procNum;
}
void schedule() {
if (!runningList.empty()) {
PCB *pcb = runningList.randPop();
if ((pcb->time -= timeSlice) > 0) {
pcb->pstate = PState::ready;
readyList.push(pcb);
pcbSched[0] = PCBSched(pcb, PState::running, PState::ready);
} else {
pcb->time = 0;
pcb->pstate = PState::free;
freeList.push(pcb);
pcbSched[0] = PCBSched(pcb, PState::running, PState::free);
}
} else {
pcbSched[0].pcb = nullptr;
}
if (!readyList.empty()) {
PCB *pcb = readyList.randPop();
pcb->pstate = PState::running;
runningList.push(pcb);
pcbSched[1] = PCBSched(pcb, PState::ready, PState::running);
} else {
pcbSched[1].pcb = nullptr;
}
}
char *__pStateToStr(char *dest, PState pState) {
switch (pState) {
case PState::free:
strcpy(dest, "Free");
break;
case PState::ready:
strcpy(dest, "Ready");
break;
case PState::running:
strcpy(dest, "Running");
break;
}
return dest;
}
void printInfo() {
char infoTemp[2][40];
if (pcbSched[1].pcb == nullptr) {
printf("Sched: %s\n", \
pcbSched[0].getInfo(infoTemp[0]));
} else if (pcbSched[0].pcb == nullptr) {
printf("Sched: %s\n", \
pcbSched[1].getInfo(infoTemp[0]));
} else {
printf("Sched: %s, %s\n", \
pcbSched[0].getInfo(infoTemp[0]), pcbSched[1].getInfo(infoTemp[1]));
}
printf("Running: ");
runningList.printList();
printf("Ready: ");
readyList.printList();
printf("Free: ");
freeList.printList();
printf("\n");
}
运行结果
同系列
2、操作系统 程序设计作业2——进程调度 (C++实现)
https://blog.csdn.net/qq_40939814/article/details/103548436
3、操作系统 程序设计作业3——进程同步(信号量机制) (C++伪代码实现)
https://blog.csdn.net/qq_40939814/article/details/103548527
5、操作系统 程序设计作业5——模拟分页系统的地址变换(公式法和硬拼法) (C++实现)
https://blog.csdn.net/qq_40939814/article/details/103548645