Diretório do artigo
Título
Por favor, escreva um programa para simular o agendamento de vários processos. Suponha que o estado do processo esteja dividido em dois tipos de execução e pronto.
Cada processo pode ser representado por seu PCB, sem criar um processo real.
O PCB é organizado em uma lista vinculada e é dividido em três filas:
freeQueue: uma fila de PCB em branco
readyQueue: uma fila pronta
runningQueue: uma fila de execução
Quando o programa começa a executar, o usuário digita o número de processos n e o tempo t0 / t1 /.../ tn que cada processo precisa executar.
O programa pega o processo de criação de PCB da fila de PCB em branco e o insere no readyQueue.
O processo é agendado de maneira aleatória , ou seja, um processo é selecionado aleatoriamente na fila pronta e colocado em operação (ou seja, a variável de estado no PCB é atribuída a "executar"). Modifique de forma correspondente a fila onde está, e o processo que estava originalmente no estado em execução precisa ser alterado para o estado "pronto" e inserido no readyQueue.
Supondo que o intervalo de tempo seja 2, depois de cada vez que o processo está agendado, o tempo que ainda precisa ser executado deve ser reduzido em 2 até atingir 0, o que significa que o processo está concluído. Precisa reciclar PCB para freeQueue .
Sempre que ocorre o agendamento, um exemplo das informações que precisam ser impressas é:
Programar: P0 (Em execução -> Pronto), P3 (Pronto -> Em execução) Em
execução: P3
Pronto: P1-> P2-> P0
As informações acima indicam que P0 está no estado de execução durante o agendamento e P3 está selecionado para execução.O PCB do processo P0 entra na fila de pronta e está no final da fila. A fila pronta deve gerar o nome do processo na ordem dos nós da fila.
Exemplo de código de trecho:
#define free 0
#define ready 1
#define running 2
#define ts 2 / * intervalo de tempo /
struct PCB {
int pid; / ID do processo /
int pstate; / state do processo * /
char pname; / nome da imagem /
int ptime; / tempo de execução restante * /
struct PCB pnext; / next PCB * /
}
Código
//
// 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");
}
Resultado da operação
Mesma série
2. Planejamento de 2 processos da tarefa de programação do sistema operacional (implementado por C ++)
https://blog.csdn.net/qq_40939814/article/details/103548436
3. Sincronização de 3 processos da tarefa de programação do sistema operacional (mecanismo de semáforo) (implementação de pseudocódigo em C ++)
https://blog.csdn.net/qq_40939814/article/details/103548527
5. Operação de programação do sistema operacional Conversão de 5 endereços do sistema de paginação analógica (método de fórmula e método de ortografia rígida) (implementação C ++)
https://blog.csdn.net/qq_40939814/article/details/103548645