Operating System Practicals!
Operating System Practicals!
Aim:
To implement the Producer-Consumer problem using shared memory in C and understand inter-
process communication and synchronization using semaphores.
Tools Used:
Programming Language: C
Learning Objectives:
Theory:
1. Introduction
The Producer-Consumer problem is a classical example of process synchronization in
operating systems.
It illustrates how two types of processes—producers and consumers—share a common
buffer in a coordinated way to prevent conflicts.
This experiment demonstrates shared memory for inter-process communication and
semaphores for synchronization, ensuring that producers do not overwrite unconsumed data
and consumers do not read empty buffer slots.
The fork() system call enables concurrent execution of producer and consumer processes,
while semaphores ensure mutual exclusion and orderly execution.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
3. Summary
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER_SIZE 10
#define SHM_KEY 0x1234
#define SEM_KEY 0x5678
// Semaphore indices
#define MUTEX 0
#define EMPTY 1
#define FULL 2
int main() {
int shmid, semid;
SharedBuffer *shm;
// Create semaphores
semid = semget(SEM_KEY, 3, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget failed");
exit(1);
}
// Initialize semaphores
union semun arg;
[Link] = 1;
semctl(semid, MUTEX, SETVAL, arg); // mutex = 1
[Link] = BUFFER_SIZE;
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
// Fork process
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
} else if (pid == 0) {
// Consumer Process
int i;
for (i = 0; i < 10; i++) {
sem_wait_op(semid, FULL);
sem_wait_op(semid, MUTEX);
sem_signal_op(semid, MUTEX);
sem_signal_op(semid, EMPTY);
sleep(1);
}
shmdt((void *) shm);
} else {
// Producer Process
int i;
for (i = 0; i < 10; i++) {
int item = i + 1;
sem_wait_op(semid, EMPTY);
sem_wait_op(semid, MUTEX);
shm->buffer[shm->in] = item;
printf("Producer produced: %d\n", item);
shm->in = (shm->in + 1) % BUFFER_SIZE;
sem_signal_op(semid, MUTEX);
sem_signal_op(semid, FULL);
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
sleep(1);
}
// Cleanup
shmdt((void *) shm);
shmctl(shmid, IPC_RMID, NULL);
semctl(semid, 0, IPC_RMID);
}
return 0;
}
Output:
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Learning Outcomes:
Course Outcomes:
Conclusion:
Successfully implemented synchronized producer and consumer processes using shared memory and
semaphores. Efficiently managed the circular buffer, ensured orderly production and consumption,
and avoided race conditions, thereby fulfilling the aim of demonstrating a robust inter-process
communication system in C.
Viva Questions:
Aim:
To implement the Producer-Consumer problem using message passing in C and understand inter-
process communication, synchronization, and coordination between processes via a message queue.
Tools Used:
Programming Language: C
Learning Objectives:
Theory:
1. Introduction
The fork() system call is used to create a consumer process, while the producer process
sends messages to the message queue. The consumer receives messages, ensuring orderly
communication.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
• Definition: fork() creates a child process that runs concurrently with the parent
process.
• Purpose in this Experiment:
o Parent process: Producer
o Child process: Consumer
o Both execute simultaneously and communicate through the message queue.
• Code Mapping:
3. Summary
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/wait.h>
// Message structure
struct message {
long msg_type;
int data;
};
int main() {
int msgid;
pid_t pid;
pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
}
if (pid == 0) {
// Consumer process
struct message msg;
for (int i = 0; i < NUM_ITEMS; i++) {
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
return 0;
}
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Output:
Learning Outcomes:
Course Outcomes:
Conclusion:
Successfully implemented synchronized producer and consumer processes using message passing in
C. Efficiently coordinated message sending and receiving to maintain the correct order of data
transfer, ensured orderly production and consumption, and avoided message loss, thereby fulfilling
the aim of demonstrating a robust inter-process communication system.
Viva Questions:
Aim:
To write a multithreaded program in C that calculates the summation of non-negative integers using
the Runnable-like approach with threads, ensuring synchronized updates to a shared sum variable.
Tools Used:
Programming Language: C
Learning Objectives:
Theory:
1. Introduction
Multithreading allows a program to execute multiple threads concurrently, improving
efficiency for computational tasks. In this experiment, threads are used to calculate the
summation of non-negative integers. Each thread computes a partial sum over a specific
range, and the results are accumulated into a shared global sum. Synchronization is
maintained using a mutex, ensuring that updates to the global sum are thread-safe and free
from race conditions.
2. Multithreading
• Definition: Each thread needs parameters specifying the range of numbers it will
sum. In C, we define a structure ThreadData containing start and end.
• Code Mapping:
typedef struct {
int start;
int end;
} ThreadData;
• Joining Threads: The main thread waits for all child threads to finish using
pthread_join().
pthread_join(threads[i], NULL);
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
pthread_mutex_lock(&sum_mutex);
global_sum += local_sum;
pthread_mutex_unlock(&sum_mutex);
• Purpose: Ensures race conditions are avoided, and the final global sum is correct.
• Logic: The total range 0…N is divided among threads to balance workload:
1. chunk_size = (N + 1) / num_threads
2. remainder = (N + 1) % num_threads
• Assignment: Threads get chunk_size numbers, and the first remainder threads
receive 1 extra number to cover all integers.
• Code Mapping:
thread_data[i].start = start;
thread_data[i].end = start + chunk_size - 1;
if (remainder > 0) {
thread_data[i].end++;
remainder--;
}
start = thread_data[i].end + 1;
3. Summary
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_THREADS 10
// Thread function
void* partial_sum(void* arg) {
ThreadData* data = (ThreadData*) arg;
long long local_sum = 0;
pthread_exit(NULL);
}
int main() {
int N, num_threads;
pthread_t threads[MAX_THREADS];
ThreadData thread_data[MAX_THREADS];
// Input N
printf("Enter a non-negative integer N: ");
scanf("%d", &N);
if (N < 0) {
printf("Error: N must be non-negative.\n");
return 1;
}
// Initialize mutex
pthread_mutex_init(&sum_mutex, NULL);
// Join threads
for (int i = 0; i < num_threads; i++) {
pthread_join(threads[i], NULL);
}
// Destroy mutex
pthread_mutex_destroy(&sum_mutex);
// Print result
printf("Sum of 0 to %d = %lld\n", N, global_sum);
return 0;
}
Output:
Learning Outcomes:
Course Outcomes:
Conclusion:
Viva Questions:
1. What is the purpose of using threads in this program instead of sequential execution?
2. How does the pthread_mutex_t ensure synchronization of the global sum?
3. How is the workload divided among multiple threads in this program?
4. What is the role of pthread_create() and pthread_join() in thread management?
5. What could happen if mutex locks were not used when updating the shared variable?
Aim: To write a multithreaded C program that outputs all prime numbers less than or equal to a user-
specified number, demonstrating concurrent execution using threads.
Tools Used:
Programming Language: C
Learning Objectives:
Theory:
1. Introduction
Multithreading allows a program to execute multiple threads concurrently within a single
process. Each thread operates independently but shares the same process memory,
enabling efficient parallel execution of tasks. In this experiment, multithreading is used to
find all prime numbers less than or equal to a user-specified number. Each thread is
responsible for checking a subset of numbers, allowing the workload to be divided and
executed concurrently. This approach demonstrates practical multithreading, task
division, and parallel computation in C using the pthread library.
• Definition: A prime number is a natural number greater than 1 that has no positive
divisors other than 1 and itself.
• Prime Checking Logic:
1. Numbers less than 2 are not prime.
2. 2 is the first prime number.
3. Even numbers greater than 2 are not prime.
4. Odd numbers are checked by dividing them by all odd integers up to their
square root.
• Code Mapping:
• Definition: Each thread requires information about the range of numbers it will
check. This is achieved using a ThreadData structure containing start and end.
• Code Mapping:
typedef struct {
int start;
int end;
} ThreadData;
• Purpose: Divides the overall range among threads to balance workload and ensure all
numbers are processed.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
• Definition: Threads are created using pthread_create(). Each thread executes the
function find_primes(), which checks numbers in its assigned range.
• Joining Threads: The main program waits for all threads to complete using
pthread_join().
• Code Mapping:
• Logic: The total numbers from 2 to N are divided among num_threads threads:
1. range = (N - 1) / num_threads
2. The last thread may handle any remaining numbers to cover all integers up to N.
• Code Mapping:
3. Summary
Flag Purpose
-lm Links the math library (libm) for functions like sqrt(), pow(), etc.
-lpthread Links the POSIX threads library for pthread_create(), pthread_join(),
etc.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#define MAX_THREADS 10
int main() {
int N, num_threads;
pthread_t threads[MAX_THREADS];
ThreadData thread_data[MAX_THREADS];
return 0;
}
Output:
Learning Outcomes:
Course Outcomes:
Conclusion:
Viva Questions:
1. What is the purpose of using threads in this program instead of sequential execution?
2. How is the range of numbers divided among multiple threads?
3. What is the role of the pthread_create() and pthread_join() functions?
4. How does the program ensure correct identification of prime numbers in a concurrent
environment?
5. Why is the is_prime() function necessary, and how does it work?
Aim:
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the concept of thread synchronization and how it helps in coordinating producer and
consumer threads.
2. Learn how to use mutexes to ensure mutual exclusion while accessing shared resources.
3. Apply condition variables to signal and wait for buffer state changes (full/empty).
4. Implement a bounded buffer using threads to manage concurrent production and consumption.
Theory:
1. Introduction
In concurrent programming, multiple threads may need to access and manipulate shared
resources simultaneously. If proper synchronization is not enforced, this can lead to race
conditions, inconsistent data, or program crashes. The Bounded Buffer problem (a version
of the Producer-Consumer problem) is a classical example used to illustrate thread
coordination and synchronization mechanisms.
In this problem:
• A producer thread generates data items and places them into a fixed-size buffer.
• A consumer thread removes items from the buffer for processing.
• The buffer has a maximum capacity, so the producer must wait if the buffer is full,
and the consumer must wait if the buffer is empty.
• Definition: A design pattern where producers create data and consumers process it
using a shared buffer.
• Key Points:
1. Producer: Adds items to the buffer. Must wait if the buffer is full.
2. Consumer: Removes items from the buffer. Must wait if the buffer is empty.
3. Buffer State Management: Ensures that no data is lost, overwritten, or
skipped.
• Example Table – Buffer Operations:
This table shows how producers and consumers coordinate through the buffer state, waiting
when necessary.
• Definition: Condition variables are used to make threads wait for a particular
condition before proceeding.
• Purpose in Experiment:
o Producer waits when the buffer is full (count == BUFFER_SIZE).
o Consumer waits when the buffer is empty (count == 0).
o They allow threads to sleep instead of busy-waiting, improving efficiency.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
• Code Mapping:
• Definition: A circular buffer allows the producer and consumer to wrap around the
array when the end is reached, efficiently using space.
• Implementation in Experiment:
o in points to the index where the producer will add the next item.
o out points to the index where the consumer will remove the next item.
o Indices are updated using modulo operation: (index + 1) % BUFFER_SIZE.
• Benefit: Avoids shifting elements and ensures smooth continuous operation.
1. Initialize a buffer of fixed size, a mutex, and two condition variables (not_full,
not_empty).
2. Producer thread:
o Generate items one by one.
o Wait if the buffer is full (pthread_cond_wait).
o Insert item into buffer and update in and count.
o Signal consumer that buffer is not empty (pthread_cond_signal).
3. Consumer thread:
o Wait if buffer is empty (pthread_cond_wait).
o Remove item from buffer and update out and count.
o Signal producer that buffer is not full (pthread_cond_signal).
4. Repeat until all items are produced and consumed.
5. Wait for threads to complete using pthread_join.
6. Destroy mutex and condition variables.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
3. Summary
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define BUFFER_SIZE 5
#define PRODUCE_COUNT 10
int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
int count = 0;
pthread_mutex_t mutex;
pthread_cond_t not_full;
pthread_cond_t not_empty;
pthread_mutex_lock(&mutex);
buffer[in] = item;
printf("Producer produced: %d\n", item);
in = (in + 1) % BUFFER_SIZE;
count++;
pthread_exit(NULL);
}
while (count == 0) {
// Buffer is empty, wait for not_empty signal
pthread_cond_wait(¬_empty, &mutex);
}
pthread_exit(NULL);
}
int main() {
pthread_t prod_thread, cons_thread;
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
return 0;
}
Output:
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Learning Outcomes:
Course Outcomes:
Conclusion:
Viva Questions:
1. What is the bounded buffer problem, and why is synchronization required in this scenario?
2. Explain how mutexes ensure mutual exclusion in the producer-consumer program.
3. What role do condition variables play in managing full and empty buffer states?
4. Describe how a circular buffer is implemented in this experiment and its advantages.
5. What could happen if synchronization primitives were not used in this multithreaded program?
Aim:
Tools Used:
Programming Language: C
Learning Objectives:
3. Apply mutex locks to protect shared resources and prevent race conditions.
4. Coordinate access so that multiple readers can read simultaneously, but writers get exclusive
access.
5. Observe and analyze the behavior of synchronized reader and writer threads in a controlled
environment.
Theory:
1. Introduction
In multithreaded programming, multiple threads often need to access shared resources
simultaneously. Improper access can cause race conditions, data inconsistency, or program
crashes.
This experiment demonstrates how to synchronize readers and writers using mutexes to
ensure:
Key Points:
Purpose in Experiment:
Code Mapping:
Purpose in Experiment:
Code Mapping:
pthread_mutex_lock(&write_lock);
// Write operation
pthread_mutex_unlock(&write_lock);
Purpose: Allows multiple readers to read concurrently while blocking writers only if
necessary.
• Lock write_lock.
• Write to shared resource.
• Unlock write_lock.
Purpose: Ensures that writers have exclusive access, preventing any readers from accessing
data while writing.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
3. Summary
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
// Shared resource
int shared_data = 0;
pthread_mutex_lock(&mutex);
read_count++;
if (read_count == 1) {
// First reader locks writers out
pthread_mutex_lock(&write_lock);
}
pthread_mutex_unlock(&mutex);
// Reading (simulated)
printf("Reader %d: reading shared_data = %d\n", id, shared_data);
sleep(1); // Simulate read time
pthread_mutex_lock(&mutex);
read_count--;
if (read_count == 0) {
// Last reader unlocks writers
pthread_mutex_unlock(&write_lock);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void* writer(void* arg) {
int id = *((int*)arg);
pthread_mutex_lock(&write_lock);
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
// Writing (simulated)
shared_data += 10;
printf("Writer %d: writing shared_data = %d\n", id, shared_data);
sleep(1); // Simulate write time
pthread_mutex_unlock(&write_lock);
pthread_exit(NULL);
}
int main() {
pthread_t readers[5], writers[2];
int reader_ids[5] = {1, 2, 3, 4, 5};
int writer_ids[2] = {1, 2};
// Initialize mutexes
pthread_mutex_init(&mutex, NULL);
pthread_mutex_init(&write_lock, NULL);
// Destroy mutexes
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&write_lock);
return 0;
}
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Output:
Note:
The exact order of output may vary across executions because threads in a multithreaded program
execute concurrently. The operating system’s thread scheduler determines the sequence of
execution, leading to minor variations each time the program runs. However, the synchronization
ensures that:
Learning Outcomes:
Course Outcomes:
Conclusion:
Viva Questions:
1. What is the purpose of using separate mutexes for readers and writers?
2. How does the program ensure that multiple readers can read simultaneously?
3. How does the program prevent writers from accessing the shared data while readers are reading?
4. What happens if the read_count variable is not properly synchronized?
5. Why is it important to destroy the mutexes at the end of the program?
Aim:
To implement the Sleeping Barber problem in C using threads, mutexes, and condition variables to
manage synchronization between the barber and multiple customers, ensuring proper coordination
of sleeping, waking, and servicing behavior.
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the Sleeping Barber problem and its significance in process synchronization.
2. Learn to implement multiple customer threads and a barber thread using pthreads in C.
3. Apply mutex locks and condition variables to coordinate access between barber and customers.
4. Ensure that the barber sleeps when no customers are present and wakes up when a customer
arrives.
5. Observe and analyze how concurrent threads manage limited resources (chairs) to prevent race
conditions.
Theory:
1. Introduction
The Sleeping Barber problem is a classic synchronization problem in operating systems and
concurrent programming. It models a barber shop scenario to illustrate thread coordination
and resource sharing.
The problem highlights how multiple threads (barber and customers) interact with a shared
resource (the barber and chairs) while avoiding race conditions, lost signals, and ensuring
correct order of operations.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
• A mutex ensures that only one thread at a time can access critical sections, like
updating waiting_customers.
• Without a mutex, multiple customers arriving simultaneously could corrupt shared
data, causing incorrect counts or missed haircuts.
Code Reference:
Code Reference:
3. Summary
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_CUSTOMERS 10
#define NUM_CHAIRS 3
// Condition variables
pthread_cond_t barber_ready;
pthread_cond_t customer_ready;
// Shared variables
int waiting_customers = 0;
int barber_sleeping = 1;
// Wait if no customers
while (waiting_customers == 0) {
printf("Barber: No customers, going to sleep.\n");
pthread_cond_wait(&customer_ready, &mutex);
}
waiting_customers--;
printf("Barber: Cutting hair. Waiting customers: %d\n",
waiting_customers);
// Simulate haircut
sleep(2);
printf("Barber: Done cutting hair.\n");
}
return NULL;
}
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t barber_thread;
pthread_t customer_threads[NUM_CUSTOMERS];
pthread_cond_init(&barber_ready, NULL);
pthread_cond_init(&customer_ready, NULL);
// Clean up
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&barber_ready);
pthread_cond_destroy(&customer_ready);
return 0;
}
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Output:
Learning Outcomes:
1. Successfully understood the Sleeping Barber problem and its significance in process
synchronization.
2. Successfully implemented multiple customer threads and a barber thread using pthreads in C.
3. Successfully applied mutex locks and condition variables to coordinate access between barber
and customers.
4. Successfully ensured that the barber sleeps when no customers are present and wakes up when
a customer arrives.
5. Successfully observed and verified how concurrent threads manage limited resources (chairs) to
prevent race conditions.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Course Outcomes:
Conclusion:
Viva Questions:
1. What is the purpose of using mutexes and condition variables in the Sleeping Barber problem?
2. How does the program ensure that the barber sleeps when no customers are present?
3. How are waiting customers managed when there are limited chairs?
4. What happens if mutexes are not used in this program?
5. Why is it necessary to cancel or stop the barber thread at the end of the program?
Aim:
To implement the First-Come, First-Served (FCFS) CPU scheduling algorithm in C, calculate the waiting
time and turnaround time for each process, and determine the average waiting and turnaround times.
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the concept of CPU Scheduling and its importance in process management.
2. Learn the working principle of the First Come First Serve (FCFS) scheduling algorithm.
3. Implement the FCFS scheduling algorithm using C programming.
4. Calculate and analyze Waiting Time and Turnaround Time for multiple processes.
5. Evaluate the performance of FCFS scheduling by computing average waiting and turnaround times
for given inputs.
Theory:
1. Introduction
In an operating system, multiple processes compete for CPU time. The CPU scheduler
decides which process gets the CPU next based on a specific scheduling algorithm. Among
these, the First Come First Serve (FCFS) scheduling algorithm is the simplest and most
intuitive form of CPU scheduling.
The FCFS algorithm follows the FIFO (First In, First Out) principle — meaning the
process that arrives first in the ready queue gets executed first. Once the CPU is assigned to a
process, it runs till completion without being preempted or interrupted by another process.
This type of scheduling is non-preemptive, meaning that once the CPU starts executing a
process, it cannot stop until that process completes. Any new process arriving in the
meantime must wait until the current one is finished.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Real-life Analogy:
Imagine a queue at a movie ticket counter. The customer who comes first is served first, and
others wait in line until it’s their turn. Similarly, in FCFS scheduling, processes are served in
the order they arrive.
This simple idea ensures fairness — every process gets a turn — but can also cause
inefficiency if long processes arrive before shorter ones, leading to what’s called the convoy
effect, where shorter processes are delayed unnecessarily.
The FCFS scheduling algorithm schedules processes based solely on their arrival time.
The key characteristic is no preemption — once a process starts, it keeps the CPU until it
finishes execution.
If the CPU becomes idle (no process in the queue), it simply waits until the next process
arrives.
Term Description
Arrival Time (AT) The time at which a process arrives and becomes ready for
execution.
Burst Time (BT) The total amount of CPU time required by a process for
execution.
Completion Time (CT) The time at which a process finishes execution.
Waiting Time (WT) The total time a process spends waiting in the ready queue before
getting CPU time.
Formula: WT = Start Time – Arrival Time
Turnaround Time (TAT) The total time taken from process arrival to its completion.
Formula: TAT = WT + BT
Average Waiting Time The average of all waiting times.
(AWT) Formula: AWT = ΣWT / n
Average Turnaround Time The average of all turnaround times.
(ATAT) Formula: ATAT = ΣTAT / n
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
• The number of processes and their arrival and burst times are entered.
• The processes are sorted by their arrival time, ensuring that the earliest arriving
process executes first.
This gives a clear picture of how long processes waited and how efficiently the CPU was
utilized.
Since P1 and P2 arrive together, P1 is taken first because it appears first in the list.
So, the order of execution: P1 → P2 → P4 → P3
Step 3: Averages
6. Advantages of FCFS
7. Disadvantages of FCFS
8. Real-world Analogy
9. Summary
The FCFS scheduling algorithm is the foundation for understanding CPU scheduling.
It ensures fairness and is easy to implement, but it is not efficient for all types of workloads
due to the convoy effect.
In short, FCFS helps students grasp the fundamental mechanics of process scheduling,
serving as a stepping stone to advanced algorithms like SJF, Round Robin, and Priority
Scheduling.
The Gantt chart represents the timeline of process execution. For the earlier example:
Step-by-step timeline:
• Idle period (0–3): CPU waits for the first process to arrive.
• Execution blocks: Each process executes continuously for its burst time.
• Completion times: P1 = 11, P2 = 16, P4 = 23, P3 = 28
Code:
#include <stdio.h>
typedef struct {
int pid;
int arrival_time;
int burst_time;
int waiting_time;
int turnaround_time;
} Process;
int main() {
int n;
Process p[100];
scanf("%d", &n);
calculateTimes(p, n);
printTable(p, n);
calculateAverage(p, n);
return 0;
}
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Output:
Learning Outcomes:
1. Successfully understood the First-Come, First-Served (FCFS) scheduling algorithm and its role in
process scheduling.
2. Successfully implemented process scheduling in C using arrays and structures.
3. Successfully calculated waiting times and turnaround times for multiple processes.
4. Successfully handled processes based on their arrival times, ensuring correct execution order.
5. Successfully computed and verified average waiting time and average turnaround time for all
processes.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Course Outcomes:
Conclusion:
The First-Come, First-Served (FCFS) scheduling algorithm was successfully implemented in C. The
program demonstrated how processes are scheduled based on their arrival times, calculated
individual waiting and turnaround times accurately, and computed average waiting and turnaround
times for all processes. Through this practical, students observed the behavior of FCFS scheduling,
understood its advantages and limitations, and gained hands-on experience in process management,
sequence execution, and performance analysis in operating systems.
Viva Questions:
1. What is the main principle behind the First-Come, First-Served (FCFS) scheduling algorithm?
2. How does the program calculate waiting time for each process?
3. How is turnaround time computed in this program?
4. What happens if two processes have the same arrival time?
5. Why is it important to sort processes by arrival time before scheduling?
Aim:
To implement the Shortest Job First (SJF) CPU scheduling algorithm without preemption in C, calculate
the waiting time and turnaround time for each process, and determine the average waiting and
turnaround times.
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the Shortest Job First (SJF) scheduling algorithm and its significance in CPU scheduling.
2. Learn the difference between preemptive and non-preemptive SJF scheduling.
3. Implement the non-preemptive SJF scheduling algorithm in C using arrays and structures.
4. Calculate waiting time, turnaround time, and completion time for multiple processes.
5. Analyze and compare the efficiency of SJF scheduling with other CPU scheduling algorithms such
as FCFS.
Theory:
1. Introduction
In operating systems, CPU scheduling is essential for managing how processes are
executed. The Shortest Job First (SJF) scheduling algorithm is a non-preemptive CPU
scheduling strategy that selects the process with the smallest burst time (execution time)
from the ready queue to execute next.
Real-life Analogy:
Imagine a print shop where multiple print jobs arrive. The printer always chooses the job that
will take the least time to complete next. This ensures shorter jobs are completed quickly,
preventing long waiting times for smaller tasks.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
• Arrival Time (AT): The time when a process enters the ready queue.
• Burst Time (BT): The CPU execution time required by the process.
• Completion Time (CT): The time at which a process finishes execution.
• Turnaround Time (TAT): Total time spent by a process from arrival to completion.
Formula: TAT = CT − AT
• Waiting Time (WT): Time a process spends waiting in the ready queue before
execution.
Formula: WT = TAT − BT
Tie-breaker Rule:
If two or more processes have the same burst time, select the one that arrived earlier.
4. Step-by-Step Example
PID AT BT CT TAT WT
P1 4 5 13 9 4
P2 3 5 8 5 0
5. Advantages of SJF
1. Minimizes average waiting time compared to FCFS.
2. Efficient for processes with known burst times.
3. Reduces the turnaround time for shorter processes.
6. Disadvantages of SJF
1. Requires prior knowledge of burst times, which may not always be available.
2. Longer processes may experience starvation if short processes keep arriving.
3. Non-preemptive version cannot adapt if a shorter process arrives while a longer
process is running.
7. Summary
Non-preemptive SJF scheduling provides an optimized way to reduce waiting time and
turnaround time for processes. It is simple, fair for shorter jobs, but may cause starvation
for longer processes. Understanding SJF lays the foundation for learning preemptive
scheduling techniques like Shortest Remaining Time First (SRTF).
8. Gantt Chart Illustration
Processes:
Time: 0 3 8 13
|----|------|------|
CPU: Idle P2 P1
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Code:
#include <stdio.h>
typedef struct {
int pid; // Process ID
int arrival_time;
int burst_time;
int completion_time;
int turnaround_time;
int waiting_time;
int is_completed;
} Process;
int main() {
int n, time = 0, completed = 0;
float total_turnaround = 0, total_waiting = 0;
Process p[100];
while (completed != n) {
int idx = -1;
int min_bt = 1e9;
if (idx != -1) {
// Process the selected job
p[idx].completion_time = time + p[idx].burst_time;
p[idx].turnaround_time = p[idx].completion_time -
p[idx].arrival_time;
p[idx].waiting_time = p[idx].turnaround_time - p[idx].burst_time;
total_turnaround += p[idx].turnaround_time;
total_waiting += p[idx].waiting_time;
time = p[idx].completion_time;
p[idx].is_completed = 1;
completed++;
} else {
// No process is ready, increment time
time++;
}
}
p[i].pid,
p[i].arrival_time,
p[i].burst_time,
p[i].completion_time,
p[i].turnaround_time,
p[i].waiting_time);
}
return 0;
}
Output:
Learning Outcomes:
1. Successfully understood the Shortest Job First (SJF) scheduling algorithm and its significance in
CPU scheduling.
2. Successfully distinguished between preemptive and non-preemptive SJF scheduling.
3. Successfully implemented the non-preemptive SJF scheduling algorithm in C using arrays and
structures.
4. Successfully calculated waiting time, turnaround time, and completion time for multiple
processes.
5. Successfully analyzed and compared the efficiency of SJF scheduling with other CPU scheduling
algorithms such as FCFS.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Course Outcomes:
Conclusion:
The non-preemptive Shortest Job First (SJF) scheduling algorithm was successfully implemented in C.
The program accurately scheduled processes based on their burst times, calculated individual waiting
times, turnaround times, and completion times, and determined the average metrics. Through this
practical, students observed how SJF minimizes average waiting time compared to FCFS, understood
the behavior of non-preemptive scheduling, and gained hands-on experience in process sequencing,
performance analysis, and efficient CPU utilization. The experiment reinforced theoretical knowledge
of CPU scheduling and demonstrated practical application in operating systems.
Viva Questions:
1. What is the main principle behind the Shortest Job First (SJF) scheduling algorithm?
2. How does non-preemptive SJF differ from preemptive SJF?
3. How are waiting time, turnaround time, and completion time calculated in this program?
4. What happens if two processes have the same burst time?
5. Why does SJF usually result in a lower average waiting time compared to FCFS?
Aim:
To implement the Round Robin (RR) CPU scheduling algorithm in C, allocate CPU time to each process
using a fixed time quantum, calculate waiting time and turnaround time for each process, and
determine the average waiting and turnaround times.
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the Round Robin (RR) scheduling algorithm and its significance in CPU scheduling.
2. Learn how time quantum affects process execution and CPU utilization.
3. Implement the Round Robin scheduling algorithm in C using arrays and structures.
4. Calculate waiting time, turnaround time, and completion time for multiple processes.
5. Analyze the performance of RR scheduling and compare it with other algorithms like FCFS and SJF.
Theory:
1. Introduction
Round Robin (RR) is a preemptive CPU scheduling algorithm designed to share the CPU
fairly among all ready processes. It assigns a fixed time slice called time quantum to each
process in the ready queue. When a process’s time quantum expires, the CPU switches to the
next process, ensuring that no process waits indefinitely.
• RR is widely used in time-sharing systems, where response time and fairness are
critical.
• Unlike FCFS, RR prevents long processes from blocking shorter ones for extended
periods.
• Preemption ensures that every process gets regular CPU attention.
• When a process executes for its TQ and is not finished, it is preempted and placed at
the end of the ready queue.
• The next process in the queue is given CPU time, and this cycle continues until all
processes are completed.
• RR is effective for interactive systems where response time and fairness are critical.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Real-life Analogy:
Imagine multiple customers at a single ATM. Each customer is allowed to use the machine
for a fixed time (time quantum). Once their time expires, the next customer uses the ATM,
and the previous customer waits for their next turn. This cycle continues until all customers
are done.
Term Description
Time Quantum (TQ) Fixed duration for which a process executes before preemption.
Arrival Time (AT) Time at which a process enters the ready queue.
Burst Time (BT) Total CPU time required by a process.
Remaining Time (RT) Remaining CPU time for the process to complete.
Waiting Time (WT) Total time a process spends waiting in the ready queue.
Turnaround Time (TAT) Total time taken from process arrival to completion.
Completion Time (CT) Time at which a process finishes execution.
Formulas:
1. Initialize time = 0.
2. Input arrival time, burst time, and time quantum for all processes.
3. Initialize remaining_time = burst_time for all processes.
4. Repeat until all processes are completed:
a. For each process in the ready queue:
o If arrival_time <= time and remaining_time > 0:
▪ If remaining_time > TQ, execute for TQ and update
remaining_time -= TQ.
▪ Else, execute for remaining_time and mark process as completed.
▪ Update completion_time, turnaround_time, and waiting_time.
o If no process has arrived, increment time.
5. Calculate average waiting time and average turnaround time.
6. Display the results in tabular form.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
4. Step-by-Step Working
Observations:
Example:
Input:
Process AT BT
P1 0 5
P2 1 3
P3 2 1
Step-by-step Execution:
Formulas:
Observations:
6. Advantages of RR Scheduling
7. Disadvantages of RR Scheduling
8. Summary
Round Robin scheduling is a preemptive, fair, and cyclic CPU allocation strategy. It
ensures all processes get CPU attention, prevents starvation, and is highly suitable for
interactive systems. Proper selection of time quantum balances response time and CPU
efficiency. Gantt charts illustrate the execution timeline and help calculate waiting and
turnaround times.
Code:
#include <stdio.h>
typedef struct {
int pid;
int burst_time;
int remaining_time;
int waiting_time;
int turnaround_time;
int arrival_time;
} Process;
int main() {
int n, time_quantum, time = 0, completed = 0;
Process p[100];
int done;
// Display results
printf("\nPID\tAT\tBT\tWT\tTAT\n");
float total_wt = 0, total_tat = 0;
for (int i = 0; i < n; i++) {
printf("P%d\t%d\t%d\t%d\t%d\n",
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
p[i].pid,
p[i].arrival_time,
p[i].burst_time,
p[i].waiting_time,
p[i].turnaround_time);
total_wt += p[i].waiting_time;
total_tat += p[i].turnaround_time;
}
return 0;
}
Output:
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Learning Outcomes:
1. Successfully understood the Round Robin (RR) scheduling algorithm and its significance in CPU
scheduling.
2. Successfully learned how time quantum affects process execution and CPU utilization.
3. Successfully implemented the Round Robin scheduling algorithm in C using arrays and structures.
4. Successfully calculated waiting time, turnaround time, and completion time for multiple
processes.
5. Successfully analyzed the performance of RR scheduling and compared it with other algorithms
like FCFS and SJF.
Course Outcomes:
Students successfully developed a comprehensive understanding of CPU scheduling using the Round
Robin (RR) algorithm. They implemented the RR scheduling algorithm in C, calculated waiting time,
turnaround time, and completion time for multiple processes, and observed the effect of time
quantum on CPU utilization and process execution order. Through this practical, students gained
practical skills in evaluating RR performance, comparing it with other scheduling algorithms like FCFS
and SJF, and managing multiple processes efficiently in a simulated environment.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Conclusion:
The Round Robin (RR) scheduling algorithm was successfully implemented in C. The program
accurately scheduled processes based on their arrival times and time quantum, calculated individual
waiting times, turnaround times, and completion times, and determined the average metrics. Through
this practical, students observed how RR ensures fair CPU allocation, efficient process rotation, and
minimized starvation, thereby achieving the aim of demonstrating practical process scheduling,
performance analysis, and effective CPU utilization in operating systems.
Viva Questions:
1. What is the main principle behind the Round Robin (RR) scheduling algorithm?
2. How does the time quantum affect the execution and waiting time of processes?
3. How are waiting time, turnaround time, and completion time calculated in this program?
4. What happens if a process’s burst time is less than the time quantum?
5. How does Round Robin compare to FCFS and SJF in terms of fairness and CPU utilization?
Aim:
To implement the Banker's Algorithm in C to determine whether the system is in a safe state, calculate
the need matrix, and find a safe sequence of process execution if it exists.
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the Banker's Algorithm and its role in deadlock avoidance in operating systems.
4. Calculate the Need matrix and track resource allocation for multiple processes.
Theory:
1. Introduction
The Banker's Algorithm is a deadlock avoidance algorithm in operating systems. It ensures
that resource allocation never leads the system into an unsafe state. Each process declares its
maximum resource requirement, and the system checks whether granting requests keeps it in
a safe state. This algorithm is especially significant in multi-processing systems where
deadlocks must be prevented.
Term Description
Allocation Resources currently assigned to a process.
Max Maximum resources a process may need.
Need Remaining resources a process may request (Need = Max − Allocation).
Available Resources currently available for allocation.
Safe State A state where there exists at least one sequence of execution allowing all
processes to finish.
Unsafe A state where no safe sequence exists; could lead to deadlock.
State
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Input:
• Processes = 5, Resources = 3
• Allocation Matrix:
P0: 0 1 0
P1: 2 0 0
P2: 3 0 2
P3: 2 1 1
P4: 0 0 2
• Max Matrix:
P0: 7 5 3
P1: 3 2 2
P2: 9 0 2
P3: 2 2 2
P4: 4 3 3
• Available: 3 3 2
Execution:
Safe Sequence: P1 → P3 → P4 → P0 → P2
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
5. Gantt Chart
Time: 0 1 2 3 4 5
CPU: P1 --> P3 --> P4 --> P0 --> P2
(Here, each arrow represents the completion of a process in order of the safe sequence.)
6. Observations
7. Advantages / Disadvantages
Advantages:
Disadvantages:
8. Summary
The Banker's Algorithm is an essential deadlock avoidance technique. It simulates resource
allocation to check for safe states and ensures all processes can complete without waiting
indefinitely. Understanding this algorithm is crucial for designing reliable multi-processing
systems.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Code:
#include <stdio.h>
#define MAX_PROCESSES 10
#define MAX_RESOURCES 10
int main() {
int n, m; // Number of processes and resources
int alloc[MAX_PROCESSES][MAX_RESOURCES]; // Allocation matrix
int max[MAX_PROCESSES][MAX_RESOURCES]; // Max matrix
int need[MAX_PROCESSES][MAX_RESOURCES]; // Need matrix
int avail[MAX_RESOURCES]; // Available vector
int finish[MAX_PROCESSES] = {0}; // Finish array
int safe_seq[MAX_PROCESSES];
scanf("%d", &avail[i]);
}
return 0;
}
Output:
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Learning Outcomes:
1. Successfully understood the Banker's Algorithm and its significance in avoiding deadlocks in
operating systems.
2. Successfully learned how to calculate Need, Allocation, and Available matrices for multiple
processes and resources.
4. Successfully identified a safe sequence of process execution when the system is safe.
5. Successfully analyzed resource allocation scenarios and understood how the algorithm prevents
unsafe states and potential deadlocks.
Course Outcomes:
Conclusion:
The Banker's Algorithm was successfully implemented in C to manage resource allocation and
ensure system safety. The program accurately calculated the Need, Allocation, and Available
matrices, verified safe states, and identified safe sequences for all processes. Through this practical,
students observed how the algorithm prevents deadlocks, ensures fair resource distribution, and
maintains system stability, thereby achieving the aim of demonstrating practical deadlock avoidance
and safe resource management in operating systems.
Viva Questions:
Aim:
To implement the First-In-First-Out (FIFO) page replacement algorithm in C, simulate page requests
using a reference string, track page faults and hits, and determine the total number of page faults for
a given number of frames.
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the FIFO (First-In-First-Out) page replacement algorithm and its significance in
memory management.
2. Learn how page faults occur and how to track them in a system.
3. Implement the FIFO page replacement algorithm in C using arrays.
4. Simulate memory frames and page reference strings to observe page replacement behavior.
5. Analyze total page faults and hits to evaluate algorithm efficiency.
Theory:
1. Introduction
The FIFO (First-In-First-Out) page replacement algorithm is a classical memory management
technique used in operating systems to handle page faults. When a process references a page
that is not currently in memory, a page fault occurs. FIFO resolves this by replacing the
oldest page in memory, ensuring a simple and predictable approach to memory management.
• FIFO is commonly used in teaching operating system concepts due to its simplicity.
• Although easy to implement, FIFO does not always minimize page faults.
• It demonstrates the concept of memory frames, page hits, and page faults.
Real-life Analogy:
Imagine a queue at a ticket counter: the person who came first gets served first. Similarly, in
FIFO, the page that entered memory first is replaced first when a new page needs space.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Term Description
Page A fixed-length block of virtual memory.
Frame A fixed-length block in physical memory where a page can reside.
Page Fault Occurs when the requested page is not in memory.
Hit Occurs when the requested page is already present in memory.
FIFO First-In-First-Out replacement policy; oldest page is replaced first.
Queue Front / Used to track which page entered memory first and which is next for
Rear replacement.
Input:
• Number of frames = 5
• Page Reference String = 7, 5, 47, 5, 65, 4, 7, 7, 5
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Execution Table:
Observations:
5. Gantt Chart
Time: 0 1 2 3 4 5 6 7 8
Page: 7 5 47 5 65 4 7 7 5
Event: PF PF PF H PF PF H H H
Frames: [7 - - - -]
[7 5 - - -]
[7 5 47 - -]
[7 5 47 - -]
[7 5 47 65 -]
[7 5 47 65 4]
[7 5 47 65 4]
[7 5 47 65 4]
[7 5 47 65 4]
• PF → Page Fault
• H → Hit
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
1. FIFO always removes the page that has been in memory the longest.
2. Total page faults provide insight into the efficiency of the algorithm.
3. Page hits reduce unnecessary replacements, improving system performance.
4. FIFO is simple but can lead to more page faults in some scenarios (Belady’s
anomaly).
5. Queue-based implementation makes tracking the oldest page straightforward.
7. Advantages / Disadvantages
Advantages:
Disadvantages:
• Not optimal; may result in more page faults than other algorithms.
• Subject to Belady’s anomaly, where adding more frames increases page faults.
• Does not consider frequency or recency of page usage.
8. Summary
The FIFO page replacement algorithm provides a simple approach to handling page faults in
memory management. By replacing the oldest page in memory, it ensures a predictable and
straightforward behavior. While easy to implement, FIFO is not always the most efficient and
may result in unnecessary page faults in certain reference patterns. Understanding FIFO is
essential for grasping the fundamentals of virtual memory and page replacement strategies in
operating systems.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Code:
#include <stdio.h>
#define MAX_FRAMES 10
#define MAX_PAGES 100
int main() {
int frames[MAX_FRAMES];
int page_sequence[MAX_PAGES];
int front = 0, rear = 0;
int page_faults = 0;
int num_frames, num_pages;
// Initialize frames
for (int i = 0; i < MAX_FRAMES; i++) {
frames[i] = -1;
}
found = 1;
break;
}
}
if (!found) {
// Page fault occurs
frames[rear] = current_page;
rear = (rear + 1) % num_frames;
if (page_faults >= num_frames) {
front = (front + 1) % num_frames;
}
page_faults++;
return 0;
}
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Output:
Learning Outcomes:
1. Successfully understood the FIFO page replacement algorithm and its significance in memory
management.
2. Successfully learned how page faults occur and how they affect CPU and memory performance.
3. Successfully implemented the FIFO page replacement algorithm in C using arrays and queues.
4. Successfully tracked and calculated page faults for a given page reference string.
5. Successfully analyzed memory allocation and compared FIFO’s performance with other page
replacement strategies.
Course Outcomes:
Conclusion:
The FIFO page replacement algorithm was successfully implemented in C. The program accurately
simulated page references, maintained the frame queue, detected page hits and faults, and calculated
the total number of page faults. Through this practical, students observed how FIFO replaces the
oldest page in memory, understood the impact of frame size on page faults, and gained practical
experience in memory management techniques, thereby achieving the aim of demonstrating effective
page replacement and analyzing memory allocation efficiency.
Viva Questions:
1. What is the main principle behind the FIFO page replacement algorithm?
2. How does FIFO decide which page to replace when a page fault occurs?
3. How do the number of frames affect the number of page faults in FIFO?
4. What is the difference between a page hit and a page fault?
5. Can FIFO suffer from Belady’s anomaly? Explain.
Aim:
To implement the Least Recently Used (LRU) page replacement algorithm in C, simulate page requests
using a reference string, track page hits and page faults, and determine the total number of page faults
for a given number of memory frames.
Tools Used:
Programming Language: C
Learning Objectives:
1. Understand the Least Recently Used (LRU) page replacement algorithm and its significance in
memory management.
2. Learn how page faults occur and how LRU tracks the least recently used pages.
4. Simulate memory frames and page reference strings to observe page replacement behavior.
Theory:
1. Introduction
The Least Recently Used (LRU) page replacement algorithm is a fundamental memory
management technique in operating systems. It is used to handle page faults in virtual
memory systems by replacing the page that has not been accessed for the longest time.
• LRU is crucial in multi-tasking systems where minimizing page faults is necessary for
performance.
• By predicting that recently used pages are more likely to be used again, LRU provides
a practical approach to approximate the optimal page replacement strategy.
• This algorithm is widely implemented in operating systems, cache management, and
memory-intensive applications.
Real-life Analogy:
Consider a library with limited shelf space. When a new book arrives and all shelves are full,
the librarian removes the book that hasn’t been borrowed for the longest time. Similarly,
LRU replaces the page that has not been used for the longest duration.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Term Description
Page A fixed-length block of virtual memory.
Frame A fixed-length block in physical memory to store a page.
Page Fault Occurs when a referenced page is not in memory.
Hit Occurs when the requested page is already present in memory.
LRU Least Recently Used page replacement policy; replaces the page with the
oldest last usage.
Recent Array used to track last usage time for each frame.
Array
Formulas:
While LRU does not use formulas like CPU scheduling, the concept of "last usage time" is
crucial:
Input:
• Number of frames = 2
• Page Reference String = 4, 5, 4, 3, 4
Execution Table:
Observations:
• Initially, pages 4 and 5 caused page faults and were loaded into empty frames.
• Page 4 later caused a Hit since it was already in memory.
• Page 3 replaced page 4’s least recently used frame (page 4 had been used longer ago),
resulting in a page fault.
• Total Page Faults = 4, Total Page Hits = 1
5. Gantt Chart
Time: 0 1 2 3 4
Page: 4 5 4 3 4
Event: PF PF H PF PF
Frames: [4 -]
[4 5]
[4 5]
[3 5]
[4 3]
• PF → Page Fault
• H → Hit
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
1. LRU replaces the page that has not been accessed for the longest time.
2. Page hits reduce unnecessary replacements and improve performance.
3. The total number of page faults depends on the number of frames and the reference
string pattern.
4. LRU is more efficient than FIFO in most real-world usage patterns.
5. The algorithm requires tracking the usage of all pages, which may increase overhead.
7. Advantages / Disadvantages
Advantages:
Disadvantages:
8. Summary
The LRU page replacement algorithm efficiently handles memory by removing the least
recently used page on a page fault. By keeping track of page usage history, LRU improves
system performance and reduces page faults compared to FIFO. Understanding LRU is
crucial for optimizing memory utilization and designing effective virtual memory systems in
operating systems.
Code:
#include <stdio.h>
#define MAX_FRAMES 10
#define MAX_PAGES 100
int main() {
int frames[MAX_FRAMES], recent[MAX_FRAMES];
int page_sequence[MAX_PAGES];
int num_frames, num_pages;
int page_faults = 0, time = 0;
// Initialize frames
for (int i = 0; i < MAX_FRAMES; i++) {
frames[i] = -1;
recent[i] = -1;
}
found = 1;
recent[j] = time++; // Update usage time
break;
}
}
if (!found) {
// Page Fault
int replace_index = -1;
frames[replace_index] = current_page;
recent[replace_index] = time++;
page_faults++;
printf(" ");
}
printf("] Page Fault\n");
} else {
// Page Hit
printf("Page %d -> [", current_page);
for (int k = 0; k < num_frames; k++) {
if (frames[k] != -1)
printf("%d", frames[k]);
else
printf("-");
if (k != num_frames - 1)
printf(" ");
}
printf("] Hit\n");
}
}
return 0;
}
Output:
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Learning Outcomes:
1. Successfully understood the Least Recently Used (LRU) page replacement algorithm and its
importance in efficient memory management.
2. Successfully learned how page faults occur and how the LRU algorithm identifies and replaces
the least recently used pages.
3. Successfully implemented the LRU page replacement algorithm in C using arrays and logical
tracking mechanisms.
4. Successfully simulated memory frames and page reference strings to observe and analyze the
behavior of page replacement.
5. Successfully evaluated total page faults and hits to assess the effectiveness and performance of
the LRU algorithm.
Course Outcomes:
Conclusion:
The Least Recently Used (LRU) page replacement algorithm was successfully implemented in C. The
program accurately simulated page references, tracked page hits and faults, and maintained memory
frames based on the least recently used principle. Through this practical, students observed how LRU
minimizes unnecessary replacements compared to simpler strategies like FIFO, understood the impact
of frame size on page faults, and gained practical experience in memory management techniques. This
achieved the aim of demonstrating effective page replacement and analyzing memory allocation
efficiency in operating systems.
Viva Questions:
1. What is the main principle behind the Least Recently Used (LRU) page replacement algorithm?
2. How does LRU decide which page to replace when a page fault occurs?
3. How are page hits and page faults identified in the LRU algorithm?
4. How does the number of frames affect the total page faults in LRU?
5. Compare LRU with FIFO in terms of page replacement efficiency and practical usage.
Aim:
To implement and design a simple file system in C that simulates file creation, reading, deletion, and
listing on a virtual disk, using block-based storage management.
Tools Used:
Programming Language: C
Learning Objectives:
1. Successfully understand the structure and design of a simple file system using C.
3. Implement basic file operations: create, read, delete, and list files.
5. Analyze file system behavior, storage utilization, and block allocation efficiency.
Theory:
1. Introduction
A File System is a method and data structure that the operating system uses to control how
data is stored and retrieved on a storage medium. Without a file system, data would be one
large block, making it impossible to distinguish between different files.
This practical implements a simple file system in C using a virtual disk file, allowing us to
simulate file storage and operations without a real disk. The file system supports the
following operations:
• Create File – allocate space on the disk, store content, and update metadata.
• Read File – retrieve file content from the virtual disk.
• Delete File – remove the file’s metadata and mark blocks as free.
• List Files – display all files in the directory with their metadata.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Significance
Real-life Analogy
Term Description
Virtual Disk Simulated storage file that acts as a disk.
Block Fixed-size unit of storage on the virtual disk.
File Entry Metadata structure storing filename, starting block, number of blocks,
size, and usage flag.
Directory Array of File Entries representing all files on the disk.
Block Mechanism to assign disk blocks to a file; here, contiguous allocation is
Allocation used.
Page / Block Size of each storage block; in this case, 512 bytes.
Size
Maximum Files Maximum number of files the system can track, e.g., 100.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Input Example:
Execution Table:
6. Advantages / Disadvantages
Advantages:
Disadvantages:
7. Summary
This practical demonstrates the design of a basic file system in C using a virtual disk file.
Students gain experience in block allocation, file metadata management, and basic file
operations. By simulating file storage on a virtual disk, learners can understand how
operating systems manage disk storage, allocate space to files, and maintain directories,
achieving the aim of the experiment.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char filename[MAX_FILENAME];
int start_block;
int num_blocks;
int size;
int is_used;
} FileEntry;
FileEntry directory[MAX_FILES];
// Create a file
void create_file() {
char name[MAX_FILENAME];
char content[1024];
if (start_block == -1) {
printf("Not enough disk space!\n");
return;
}
// Add to directory
for (int i = 0; i < MAX_FILES; i++) {
if (!directory[i].is_used) {
strcpy(directory[i].filename, name);
directory[i].start_block = start_block;
directory[i].num_blocks = blocks_needed;
directory[i].size = size;
directory[i].is_used = 1;
break;
}
}
// Read a file
void read_file() {
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
char name[MAX_FILENAME];
printf("Enter file name to read: ");
scanf("%s", name);
// Delete a file
void delete_file() {
char name[MAX_FILENAME];
printf("Enter file name to delete: ");
scanf("%s", name);
int main() {
init_file_system();
int choice;
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
while (1) {
printf("\nSimple File System Menu:\n");
printf("1. Create File\n");
printf("2. Read File\n");
printf("3. Delete File\n");
printf("4. List Files\n");
printf("5. Exit\n");
printf("Enter choice: ");
scanf("%d", &choice);
switch (choice) {
case 1: create_file(); break;
case 2: read_file(); break;
case 3: delete_file(); break;
case 4: list_files(); break;
case 5: exit(0);
default: printf("Invalid choice!\n");
}
}
return 0;
}
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Output:
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Learning Outcomes:
Course Outcomes:
Students successfully developed a strong understanding of file system design and management in
operating systems. They implemented a simple file system in C, including creating, reading, listing,
and deleting files on a simulated virtual disk. Through this practical, students gained hands-on
experience in managing file metadata, block allocation, and storage space, and they learned to
ensure efficient file operations while maintaining system integrity. This practical reinforced concepts
of file handling, disk management, and memory organization in real-world operating systems.
SHRI G.P.M. DEGREE COLLEGE OF SCIENCE & COMMERCE
Department of Computer
Affiliated to University of Mumbai
Conclusion:
The simple file system was successfully implemented in C, simulating a virtual disk with block-based
storage. The program allowed users to create, read, list, and delete files while managing disk space
efficiently. Through this practical, students observed how file metadata, block allocation, and storage
management work together to provide a functional file system. The implementation reinforced the
importance of organized storage, efficient access, and proper handling of file operations, achieving
the aim of demonstrating basic file system design and management in operating systems.
Viva Questions:
1. What is the purpose of creating a virtual disk in this file system implementation?
2. How does the program keep track of files and their locations on the disk?
3. Explain how a file is read from the virtual disk. What happens if the file does not exist?
4. How does the program determine free space when creating a new file?
5. What are the advantages and limitations of this simple file system design?