Process Scheduling - OS Module Lab

As a computer engineering student, one of the most interesting aspects of our coursework is learning about operating systems (OS). Recently, in our OS module lab, we explored the concept of process scheduling, which is a fundamental part of how an operating system manages and allocates resources among multiple processes running concurrently.



In previous post, I have shared my experience in Laboratory session 1. In this blog post, I'll share my personal experience from Laboratory 2, where we implemented and analyzed two popular process scheduling algorithms: First-Come, First-Served (FCFS) and Shortest Job First (SJF). Through hands-on coding exercises in C, we gained a deeper understanding of these algorithms and their impact on process execution times and resource utilization.


First-Come, First-Served (FCFS) Scheduling

Our first task was to implement the FCFS scheduling algorithm using C. FCFS is a straightforward algorithm that follows a simple rule: processes are executed in the order they arrive in the ready queue, much like a line at the bank – the first person in the queue gets served first, and then the next person, and so on.

Here's the C program we developed:



#include <stdio.h>

struct process {
int pid; // Process ID
int bt; // Burst time
int wt, tt; // Waiting time and turnaround time
} p[10];

int main() {
int i, n, totwt, tottt, avg1, avg2;

// Get the number of processes
printf("Enter the no of process\n");
scanf("%d", &n);

// Get the burst time for each process
for (i = 1; i <= n; i++) {
p[i].pid = i;
printf("Enter the burst time n");
scanf("%d", &p[i].bt);
}

// Initialize waiting time and turnaround time for the first process
p[1].wt = 0;
p[1].tt = p[1].bt + p[1].wt;

// Calculate waiting time and turnaround time for the remaining processes
i = 2;
while (i <= n) {
p[i].wt = p[i - 1].bt + p[i - 1].wt;
p[i].tt = p[i].bt + p[i].wt;
i++;
}

// Initialize variables for total waiting time and total turnaround time
i = 1;
totwt = tottt = 0;

// Print the process details
printf("\n Process\t bt\t wt\t tt\n");
while (i <= n) {
printf("\n\t%d\t%d\t%d\t%d", p[i].pid, p[i].bt, p[i].wt, p[i].tt);
totwt = p[i].wt + totwt;
tottt = p[i].tt + tottt;
i++;
}

// Calculate and print average waiting time and average turnaround time
avg1 = totwt / n;
avg2 = tottt / n;
printf("\navg1=%d\tavg2=%d\t", avg1, avg2);

printf("\nPress Enter to continue...");
getchar(); // Wait for user to press Enter

return 0;
}


This program first asked us to enter the number of processes and their burst times (the time required for a process to complete execution). It then calculated the waiting time and turnaround time for each process based on the FCFS algorithm.

The waiting time for the first process is always 0, as it doesn't have to wait for any other process. For subsequent processes, the waiting time is calculated by adding the burst time of the previous process to the waiting time of the previous process. The turnaround time is the sum of the burst time and waiting time for a process.

After calculating these values, the program displayed the process details, including the Process ID, Burst Time, Waiting Time, and Turnaround Time. It also calculated and displayed the Average Waiting Time and Average Turnaround Time for all processes.


Shortest Job First (SJF) Scheduling

While FCFS is simple, it may not always be the most efficient scheduling algorithm, especially when dealing with processes with varying burst times. This is where the Shortest Job First (SJF) algorithm comes into play, which prioritizes processes with the shortest burst time.

Imagine a chef in a restaurant prioritizing orders that take the least amount of time to prepare, ensuring that customers don't have to wait too long for their food – that's essentially what SJF does.

Here's the C program we developed to implement SJF scheduling:



#include <stdio.h>

struct process {
int pid;
int bt;
int wt;
int tt;
} p[10], temp;

int main() {
int i, j, n, totwt, tottt;
float avg1, avg2;

printf("\nEnter the number of process:\t");
scanf("%d", &n);

for (i = 1; i <= n; i++) {
p[i].pid = i;
printf("\nEnter the burst time:\t");
scanf("%d", &p[i].bt);
}

for (i = 1; i < n; i++) {
int index = i;
for (j = i + 1; j <= n; j++) {
if (p[i].bt > p[j].bt) {
index = j;
}
}
temp = p[i];
p[i] = p[index];
p[index] = temp;
}

p[1].wt = 0;
p[1].tt = p[1].bt + p[1].wt;
i = 2;
while (i <= n) {
p[i].wt = p[i - 1].bt + p[i - 1].wt;
p[i].tt = p[i].bt + p[i].wt;
i++;
}

i = 1;
totwt = tottt = 0;
printf("\nProcess id\tbt\twt\ttt");
while (i <= n) {
printf("\n\t%d\t%d\t%d\t%d\n", p[i].pid, p[i].bt, p[i].wt, p[i].tt);
totwt = p[i].wt + totwt;
tottt = p[i].tt + tottt;
i++;
}

avg1 = (float)totwt / n;
avg2 = (float)tottt / n;
printf("\nAVG1=%f\t AVG2=%f\n", avg1, avg2);

return 0;
}


The main difference in this program was the addition of a sorting step that sorted the processes based on their burst time in ascending order. This ensured that the process with the shortest burst time was executed first, followed by the process with the next shortest burst time, and so on.

After sorting, the program calculated the waiting time and turnaround time for each process, similar to the FCFS program. Finally, it displayed the process details, including the Process ID, Burst Time, Waiting Time, and Turnaround Time, and calculated and displayed the Average Waiting Time and Average Turnaround Time.



By running these programs and comparing their outputs, we could observe the difference in the waiting times and turnaround times for processes scheduled using the FCFS and SJF algorithms.

For example, let's consider a scenario with four processes with burst times of 6, 8, 7, and 3 units, respectively. With FCFS scheduling, the average waiting time would be higher compared to SJF scheduling, as processes with longer burst times would have to wait for the processes before them to complete, even if they have shorter burst times.

In contrast, SJF scheduling executed the process with the shortest burst time (3 units) first, followed by the processes with burst times of 6, 7, and 8 units, respectively. This resulted in a lower average waiting time and potentially better resource utilization.

However, we also learned that SJF scheduling can lead to starvation for processes with longer burst times, as they may have to wait indefinitely for shorter processes to complete. This is where other scheduling algorithms, such as Round Robin or Priority Scheduling, come into play to strike a balance between efficiency and fairness.

Through this hands-on lab experience, we gained a deeper understanding of the concepts of process scheduling and the impact of different scheduling algorithms on process execution times and resource utilization. Implementing and analyzing these algorithms using C programs not only reinforced our programming skills but also provided us with valuable insights into how operating systems manage and allocate resources efficiently.

As computer engineering students, such practical experiences are invaluable in bridging the gap between theoretical concepts and real-world applications, preparing us for the challenges we may face in our future careers.

Post a Comment

Previous Post Next Post