Cpu Scheduling
Cpu Scheduling
Cpu Scheduling
CPU scheduling is a process that allows one process to use the CPU while the execution of another process
is on hold (in a waiting state) due to unavailability of any resource like I/O etc, thereby making full use of
the CPU. The aim of CPU scheduling is to make the system efficient, fast, and fair.
Whenever the CPU becomes idle, the operating system must select one of the processes in the ready queue
to be executed. The selection process is carried out by the short-term scheduler (or CPU scheduler). The
scheduler selects from among the processes in memory that are ready to execute and allocates the CPU to
one of them.
CPU Scheduling: Dispatcher
Another component involved in the CPU scheduling function is the Dispatcher. The dispatcher is the module
that gives control of the CPU to the process selected by the short-term scheduler. This function involves:
• Switching context
• Switching to user mode
• Jumping to the proper location in the user program to restart that program from where it left last
time.
The dispatcher should be as fast as possible, given that it is invoked during every process switch. The time
taken by the dispatcher to stop one process and start another process is known as the Dispatch Latency.
Dispatch Latency can be explained using the below figure:
1. When a process switches from the running state to the waiting state(for I/O request or invocation of
wait for the termination of one of the child processes).
2. When a process switches from the running state to the ready state (for example, when an interrupt
occurs).
3. When a process switches from the waiting state to the ready state (for example, completion of I/O).
5. In circumstances 1 and 4, there is no choice in terms of scheduling. A new process (if one exists in
the ready queue) must be selected for execution. There is a choice, however in circumstances 2 and
3.
6. When Scheduling takes place only under circumstances 1 and 4, we say the scheduling scheme is
non-preemptive; otherwise, the scheduling scheme is preemptive.
Non-Preemptive Scheduling
Under non-preemptive scheduling, once the CPU has been allocated to a process, the process keeps the CPU
until it releases the CPU either by terminating or by switching to the waiting state.
This scheduling method is used by the Microsoft Windows 3.1 and by the Apple Macintosh operating
systems.
It is the only method that can be used on certain hardware platforms because It does not require the special
hardware (for example a timer) needed for preemptive scheduling.
In non-preemptive scheduling, it does not interrupt a process running CPU in the middle of the execution.
Instead, it waits till the process completes its CPU burst time, and then after that, it can allocate the CPU to
any other process.
Some Algorithms based on non-preemptive scheduling are: Shortest Job First (SJF basically non-
preemptive) Scheduling and Priority (non-preemptive version) Scheduling, etc.
Preemptive Scheduling
In this type of Scheduling, the tasks are usually assigned with priorities. At times it is necessary to run a
certain task that has a higher priority before another task although it is running. Therefore, the running task
is interrupted for some time and resumed later when the priority task has finished its execution.
Thus this type of scheduling is used mainly when a process switches either from running state to ready state
or from waiting for state to ready state. The resources (that is CPU cycles) are mainly allocated to the
process for a limited amount of time and then are taken away, and after that, the process is again placed back
in the ready queue in the case if that process still has a CPU burst time remaining. That process stays in the
ready queue until it gets the next chance to execute.
Some Algorithms that are based on preemptive scheduling are Round Robin Scheduling (RR), Shortest
Remaining Time First (SRTF), Priority (preemptive version) Scheduling, etc.
#include<iostream>
using namespace std;
// function to find the waiting time for all processes
void findWaitingTime(int processes[], int n, int bt[], int wt[])
{
// waiting time for first process will be 0
wt[0] = 0;
Output:
Completion Time: Time taken for the execution to complete, starting from arrival time.
Turn Around Time: Time taken to complete after arrival. In simple words, it is the difference between the
Completion time and the Arrival time.
Waiting Time: Total time the process has to wait before its execution begins. It is the difference between
the Turn Around time and the Burst time of the process.
For the program above, we have considered the arrival time to be 0 for all the processes, try to implement a
program with variable arrival times.
As you can see in the GANTT chart above, the process P4 will be picked up first as it has the shortest burst
time, then P2, followed by P3 and at last P1.
We scheduled the same set of processes using the First come first serve algorithm in the past, and got
average waiting time to be 18.75 ms, whereas with SJF, the average waiting time comes out 4.5 ms.
#include<bits/stdc++.h>
struct Process
{
int pid; // process ID
int bt; // burst Time
};
/*
this function is used for sorting all
processes in increasing order of burst time
*/
bool comparison(Process a, Process b)
{
return (a.bt < b.bt);
}
// main function
int main()
{
Process proc[] = {{1, 21}, {2, 3}, {3, 6}, {4, 2}};
int n = sizeof proc / sizeof proc[0];
findAverageTime(proc, n);
return 0;
}
Output:
Order in which process gets executed
4231
Processes Burst time Waiting time Turnaround time
4 2 0 2
2 3 2 5
3 6 5 11
1 21 11 32
Average waiting time = 4.5
Average turnaround time = 12.5
P1 0 7 14 14-0=14 14-7=7
P2 1 3 4 4-1=3 3-3=0
P3 3 4 8 8-3=5 5-4=1
Average waiting time is calculated by adding the waiting time of all processes and then dividing them by no.
of processes.
average waiting time = waiting for time of all processes/ no.of processes
average waiting time=7+0+1=8/3 = 2.66ms
Implementation
Given below is the C++ Implementation of Shortest Remaining Time First scheduling :
Priority CPU Scheduling
In the Shortest Job First scheduling algorithm, the priority of a process is generally the inverse of the CPU
burst time, i.e., the larger the burst time the lower is the priority of that process.
In case of priority scheduling the priority is not always set as the inverse of the CPU burst time, rather it can
be internally or externally set, but yes, the scheduling is done on the basis of priority of the process where
the process which is most urgent is processed first, followed by the ones with lesser priority in order.
Processes with same priority are executed in FCFS manner.
The priority of process, when internally defined, can be decided based on memory requirements, time
limits, number of open files, ratio of I/O burst to CPU burst etc.
Whereas, external priorities are set based on criteria outside the operating system, like the importance of the
process, funds paid for the computer resource use, market factor etc.
As you can see in the GANTT chart that the processes are given CPU time just on the basis of the priorities.
Problem with Priority Scheduling Algorithm
In priority scheduling algorithm, the chances of indefinite blocking or starvation.
A process is considered blocked when it is ready to run but has to wait for the CPU as some other process is
running currently.
But in case of priority scheduling if new higher priority processes keep coming in the ready queue, then the
processes waiting in the ready queue with lower priority may have to wait for long durations before getting
the CPU for execution.
In 1973, when the IBM 7904 machine was shut down at MIT, a low-priority process was found which was
submitted in 1967 and had not yet been run.
struct Process
{
// this is the process ID
int pid;
// the CPU burst time
int bt;
// priority of the process
int priority;
};
findavgTime(proc, n);
}
// Driver code
int main()
{
Process proc[] = {{1, 10, 2}, {2, 5, 0}, {3, 8, 1}};
int n = sizeof proc / sizeof proc[0];
priorityScheduling(proc, n);
return 0;
}
P1 21 32-0=32 32-21=11
P2 3 8-0=8 8-3=5
P3 6 21-0=21 21-6=15
P4 2 15-0=15 15-2=13
Average waiting time is calculated by adding the waiting time of all processes and then dividing them by
no.of processes.
average waiting time = waiting time of all processes/ no.of processes
average waiting time=11+5+15+13/4 = 44/4= 11ms
C++ Implementation For RR Scheduling
// Program implementation in C++ for Round Robin scheduling
#include<iostream>
using namespace std;
int rem_bt[n];
for (int i = 0 ; i < n ; i++)
rem_bt[i] = bt[i];
int t = 0; // for Current time
// Let us keep traverse the processes in the round robin manner until all of them are not done.
while (1)
{
bool done = true;
// If burst time is smaller than or equal to the quantum then it is Last cycle for this process
else
{
// Increase the value of t to show how much time a process has been processed
t = t + rem_bt[i];
// As the process gets fully executed thus remaining burst time becomes 0.
rem_bt[i] = 0;
}
}
}
// Time quantum
int quantum = 2;
findavgTime(processes, x, burst_time, quantum);
return 0;
}
Output
The output of the above code is as follows:
In this case, if there are no processes on the higher priority queue only then the processes on the low priority
queues will run. For Example: Once processes on the system queue, the Interactive queue, and Interactive
editing queue become empty, only then the processes on the batch queue will run.
The Description of the processes in the above diagram is as follows:
• System Process The Operating system itself has its own process to run and is termed as System
Process.
• Interactive Process The Interactive Process is a process in which there should be the same kind of
interaction (basically an online game ).
• Batch Processes Batch processing is basically a technique in the Operating system that collects the
programs and data together in the form of the batch before the processing starts.
• Student Process The system process always gets the highest priority while the student processes
always get the lowest priority.
In an operating system, there are many processes, in order to obtain the result we cannot put all processes in
a queue; thus this process is solved by Multilevel queue scheduling.
Implementation
Given below is the C implementation of Multilevel Queue Scheduling:
#include<stdio.h>
int main()
{
int p[20],bt[20], su[20], wt[20],tat[20],i, k, n, temp;
float wtavg, tatavg;
printf("Enter the number of processes:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
p[i] = i;
printf("Enter the Burst Time of Process%d:", i);
scanf("%d",&bt[i]);
printf("System/User Process (0/1) ? ");
scanf("%d", &su[i]);
}
for(i=0;i<n;i++)
for(k=i+1;k<n;k++)
if(su[i] > su[k])
{
temp=p[i];
p[i]=p[k];
p[k]=temp;
temp=bt[i];
bt[i]=bt[k];
bt[k]=temp;
temp=su[i];
su[i]=su[k];
su[k]=temp;
}
wtavg = wt[0] = 0;
tatavg = tat[0] = bt[0];
for(i=1;i<n;i++)
{
wt[i] = wt[i-1] + bt[i-1];
tat[i] = tat[i-1] + bt[i];
wtavg = wtavg + wt[i];
tatavg = tatavg + tat[i];
}
printf("\nPROCESS\t\t SYSTEM/USER PROCESS \tBURST TIME\tWAITING
TIME\tTURNAROUND TIME");
for(i=0;i<n;i++)
printf("\n%d \t\t %d \t\t %d \t\t %d \t\t %d ",p[i],su[i],bt[i],wt[i],tat[i]);
printf("\nAverage Waiting Time is --- %f",wtavg/n);
printf("\nAverage Turnaround Time is --- %f",tatavg/n);
return 0;
}
Output
The output of the above code is as follows: