操作系统 程序设计作业2——进程调度 (C++实现)

题目

请编写一个程序,模拟若干进程调度执行的情况。假设进程的状态分为执行和就绪两种。
每个进程以其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

发布了9 篇原创文章 · 获赞 2 · 访问量 559

猜你喜欢

转载自blog.csdn.net/qq_40939814/article/details/103548436