Operating system process scheduling priority scheduling algorithm and time slice rotation algorithm

Posted by jnuneznyc on Tue, 08 Feb 2022 07:44:07 +0100

1, Experiment contents and requirements

  1. Priority law, rotation law
    Simplified assumptions
    1) The process is computational (no I/O)
    2) Process status: ready, running, finish
    3) The CPU time required by the process is determined in time slices
  2. Algorithm description
    1) Priority law - dynamic priority
    When the current running process runs out of time slices, its priority is subtracted by a constant.
    2) Rotation method
  3. requirement
    1) The value range of various random numbers generated shall be limited. For example, the CPU time required shall be limited to 1 ~ 20.
    2) The number of processes n should not be too large, usually 4 ~ 8
    3) Using dynamic data structures
    4) Independent programming

2, Experimental flow chart

3, Experimental analysis

Priority scheduling algorithm
Firstly, the time slice rotation method needs to sort the processes according to the priority in real time, and the processes with high priority run first, so the data structure of priority queue is the most appropriate.
PCB also needs to store the name of the process, the required time of the process, the priority of the process and the status of the process. Structure can be adopted, and the sorting mode of the process can be customized at the same time.
During initialization, the required time range of the process is specified as 1-20; Because each time slice ends, the time required for the process is - 1 and the priority is - 3. In order to make the priority not less than 0, the priority is specified as 60-80; The initial state of the process is ready.
When the priority scheduling algorithm is adopted, the state of the process at the head of the team is set to running each time, and then the state of each process is output. If the process status of the team leader is finish at this time, it means that all processes have been completed, that is, exit; Otherwise, after the time slice arrives, the time required by the process is - 1 and the priority is - 3, and then continue to judge whether the process has been completed. If it is completed, set the priority of the process to the minimum 0 and join the queue to ensure that the process is always at the end of the queue in the priority queue.
Round Robin
The rotation method should pay attention to understand the concept of rotation time slice, which specifies the maximum number of time slices that the process can run each time.
In the rotation method, if the occupied time slice is less than the rotation time slice, the process always runs in the CPU occupied by the head of the queue. The ordinary queue is adopted. After the head of the queue is out of line each time, it can only pop in at the end of the queue. Therefore, I adopt the data structure of double ended queue, so that when the occupied time slice is less than the rotation time slice, the process can directly pop into the head of the queue, The time complexity and space complexity are reduced.
In addition, in the rotation method, after the process is completed, it cannot be at the end of the queue like the priority queue, so I opened another queue to store the completed process.

4, Experimental code

#include <bits/stdc++.h>

using namespace std;

//*************************Priority scheduling algorithm****************************//

struct PCB_PSA {
    int id;             //Process name
    int need_time;      //Process time
    int priority;       //Priority of the process
    string state;       //Status of the process

    //Priority queue sorting: processes with high priority are executed first
    bool operator<(const PCB_PSA &a) const {
        return a.priority >= priority;
    }
};

int cnt = 1;            //Record time
int n;                  //Number of processes
char c;                 //Selective scheduling algorithm
priority_queue<PCB_PSA> pcb_PSA;

//Process initialization
void init_PSA() {
    for (int i = 1; i <= n; i++) {
        PCB_PSA t;
        t.id = i;
        t.need_time = rand() % 20 + 1;      //The process takes 1 ~ 20 minutes
        t.priority = rand() % 20 + 60;      //The process priority is 60 ~ 80, because every time a time slice is executed, the priority is - 3, and the priority will soon become negative. If this range is adopted, the minimum priority is 0
        t.state = "ready";                  //The process status is initialized to ready
        pcb_PSA.push(t);
    }
}

//Output current process operation
void print_PSA() {
    priority_queue<PCB_PSA> temp = pcb_PSA;
    PCB_PSA t;
    cout << endl << "Current time:" << cnt++ << endl;
    while (!temp.empty()) {
        t = temp.top();
        temp.pop();
        cout << "Process name:" << t.id << "\t Status:" << t.state << "\t Time required:" << t.need_time << "\t Priority:" << t.priority << endl;
    }
}

//Priority scheduling
void PSA() {
    PCB_PSA t;
    while (1) {
        //Change the status of the team leader process to running, and then output the process execution
        t = pcb_PSA.top();
        pcb_PSA.pop();
        if (t.state != "finish")t.state = "running";
        pcb_PSA.push(t);
        print_PSA();
        t = pcb_PSA.top();
        pcb_PSA.pop();
        //If the status of the queue leader process is finish, all processes are completed and exit.
        if (t.state == "finish")break;
        //Time slice arrives, process time - 1, priority - 3
        t.need_time -= 1;
        t.priority -= 3;
        //If the time required for the process is 0, set the priority to the minimum 0; Otherwise, the status changes to ready.
        if (t.need_time == 0) {
            t.state = "finish";
            t.priority = 0;
        } else {
            t.state = "ready";
        }
        pcb_PSA.push(t);
    }
}

//********************************************************************//
//***************************Time slice rotation scheduling algorithm***************************//

struct PCB_RR {
    int id;                 //Process name
    int need_time;          //Process time
    int round_time;         //Process rotation time slice
    int hold_time;          //Elapsed time of process
    string state;           //Process status
};
//pcb_finish stores the completed process
deque<PCB_RR> pcb_RR, pcb_finish;


//Process initialization
void init_RR() {
    for (int i = 1; i <= n; i++) {
        PCB_RR t;
        t.id = i;
        t.need_time = rand() % 20 + 1;      //The time required for the process ranges from 1 to 20
        t.round_time = rand() % 20 + 1;     //The process rotation time slice is 1 ~ 20
        t.hold_time = 0;                    //Initialization of process elapsed time to 0
        t.state = "ready";                  //The process status is initialized to ready
        pcb_RR.push_back(t);
    }
}

//Output current process running status + completed process status
void print_RR() {
    cout << endl << "Current time:" << cnt++ << endl;
    deque<PCB_RR> temp = pcb_RR;
    PCB_RR t;
    while (!temp.empty()) {
        t = temp.front();
        temp.pop_front();
        cout << "Process name:" << t.id << "\t Status:" << t.state << "\t Time required:" << t.need_time << "\t Rotation time slice:" << t.round_time << endl;
    }
    temp = pcb_finish;
    while (!temp.empty()) {
        t = temp.front();
        temp.pop_front();
        cout << "Process name:" << t.id << "\t Status:" << t.state << "\t Time required:" << t.need_time << "\t Rotation time slice:" << t.round_time << endl;
    }
}

//Rotation time slice
void RR() {
    PCB_RR t;
    while (!pcb_RR.empty()) {
        //Change the status of the team leader process to running, and then output the current process execution
        t = pcb_RR.front();
        pcb_RR.pop_front();
        t.state = "running";
        pcb_RR.push_front(t);
        print_RR();
        t = pcb_RR.front();
        pcb_RR.pop_front();
        //When the time slice arrives, the time required by the process is - 1, and the time occupied by the process is + 1
        t.need_time -= 1;
        t.hold_time += 1;
        //If the time required for the process is 0, the process execution is completed and enters the pcb_finish queue
        //If the occupation time = rotation time slice, the occupation time of the process is set to 0, and the team ends
        //Otherwise, the process will be the first in the team
        if (t.need_time == 0) {
            t.state = "finish";
            pcb_finish.push_back(t);
        } else if (t.hold_time == t.round_time) {
            t.state = "ready";
            t.hold_time = 0;
            pcb_RR.push_back(t);
        } else {
            pcb_RR.push_front(t);
        }
    }
    print_RR();
}

//*********************************************************************//

int main() {
    srand(time(NULL));
    cout << "Please enter the number of processes(4~8 individual): ";
    cin >> n;
    cout << "Please select a scheduling method(y: Priority law; n: Rotation method): ";
    cin >> c;
    if (c == 'y') {
        init_PSA();
        PSA();
    } else if (c == 'n') {
        init_RR();
        RR();
    }
    return 0;
}

Topics: C++ Operating System