A Practical File
of
Operating System
(CD405)
Department of Computer Science and Engineering - Data Science
Submitted by
Name:
Enrollment No:
Semester: IV
Branch: Data Science
Session: Jan Jun 2025
Department of Computer Science and Engineering
Baderia Global Institute of Engineering and Management, Jabalpur (M.P.)
Global Square, Patan Bypass, Raigwan, Jabalpur, M.P., 482002
Operating System Lab Manual (CD 405)
Contents
● Vision and Mission of the Institute
● Vision and Mission of the Department
● Program Educational Objective
● Program Outcomes
● Program Specific Outcomes
● Course Outcomes
● Laboratory Regulations and Safety Rules
● List of Experiments
Operating System (CD 405)
Vision and Mission of the Institute
Vision
Transforming life by providing professional education with excellence.
Mission
1. Quality Education: Providing Education with quality and shaping up Technocrats and
building managers with a focus on adapting to changing technologies.
2. Focused Research & Innovation: Focusing on Research and Development and fostering
Innovation among the academic community of the Institution.
3. People Focused: Accountable and committed to institutional operations for effective
functioning by Faculty members, Staff and Students.
4. Holistic Learning: Focus on conceptual learning with practical experience and experimental
learning with strong Industrial connections and collaborations.
5. Service to Society: Providing Technical and Managerial services to society for betterment of
their quality of life with best of the skills, compassion and empathy.
Operating System (CD 405)
Vision and Mission of the Department
Vision and Mission of the Department
Vision
Cultivating leaders in Data Science who drive innovation and informed decision-making through the
power of data analytics and scientific discovery.
Mission
The program strives to:
1. Foster a student-centric learning environment that equips graduates with cutting-edge knowledge and
skills in data science, analytics, and related technologies.
2. Develop professionals who can apply data-driven approaches to solve complex problems across
diverse industries, with a commitment to ethical standards and societal well-being.
3. Continuously enhance faculty expertise through ongoing training, ensuring the delivery of high-
quality education and mentorship.
4. Promote collaboration between academia and industry through research and consultancy projects,
providing students with practical experiences and opportunities for conceptual learning.
Operating System (CD 405)
Program Education Objectives
1. To impart in depth concepts of the subject in terms of both theoretical and practical aspects to
achieve excellent University Outputs.
2. To produce technically sound engineering graduates who would fulfill the latest requirements of
computer science and IT industry at modest cost with the calibre of solving intricacies of deeper
programming concepts.
3. To inculcate the lessons of communication skills, teamwork spirit and professional attitude to the
budding engineering graduates.
4. In order to get versatile growth of the students, participation of students in extracurricular
activities is also made compulsory; and also to develop ethical attitudes in the graduates so that
they can also become good citizens of the nation.
5. To develop leadership and entrepreneurship qualities in budding graduates so that they will
cherish and nourish the society and the nation with modern trends of digitization and blossom it
with their unparalleled technical expertise.
Operating System (CD 405)
Program Outcomes
1. Engineering knowledge: Apply the knowledge of mathematics, science, engineering
fundamentals, and an engineering specialization for the solution of complex engineering problems.
2. Problem analysis: Identify, formulate, research literature, and analyze complex engineering
problems reaching substantiated conclusions using first principles of mathematics, natural sciences,
and engineering sciences.
3. Design/development of solutions: Design solutions for complex engineering problems and
design system components or processes that meet the specified needs with appropriate
consideration for public health and safety, and cultural, societal, and environmental considerations.
4. Conduct investigations of complex problems: Use research based knowledge and research
methods including design of experiments, analysis and interpretation of data, and synthesis of
information to provide valid conclusions.
5. Modern tool usage: Create, select, and apply appropriate techniques, resources, and modern
engineering and IT tools, including prediction and modeling to complex engineering activities, with
an understanding of the limitations.
6. The engineer and society: Apply reasoning informed by the contextual knowledge to assess
societal, health, safety, legal and cultural issues and the consequent responsibilities relevant to the
professional engineering practice.
7. Environment and sustainability: Understand the impact of the professional engineering
solutions in societal and environmental contexts, and demonstrate the knowledge of, and need for
sustainable development.
8. Ethics: Apply ethical principles and commit to professional ethics and responsibilities and
norms of the engineering practice.
9. Individual and team work: Function effectively as an individual, and as a member or leader in
diverse teams, and in multidisciplinary settings.
10. Communication: Communicate effectively on complex engineering activities with the
engineering community and with the society at large, such as, being able to comprehend and write
effective reports and design documentation, make effective presentations, and give and receive
clear instructions.
11. Project management and finance: Demonstrate knowledge and understanding of the
engineering and management principles and apply these to one’s own work, as a member and
leader in a team, to manage projects and in multidisciplinary environments.
12. Life-long learning: Recognize the need for, and have the preparation and ability to engage in
independent and life-long learning in the broadest context of technological change.
Operating System (CD 405)
Program Specific Outcomes
Graduates will be able to-
PSO 1: Proficiency in Computer Systems: Capability to understand, analyze and develop computer
programs in the areas related algorithms, system software, multimedia, web design, cloud computing
and networking enable designing of computer systems that are efficient and support the degree of
complexity.
PSO 2: Proficiency in Software Development: Ability to understand the structure and methodologies of
software systems with keen knowledge about software design process and practical expertise in the
programming languages and the open system platform.
PSO 3: Proficiency in Mathematics and science concepts: Capable of applying mathematics and science
concepts to solve computation tasks and model real world problems using suitable algorithms and data
structures.
PSO 4: Successful career as a Computer Science Engineer: Ability to employ themselves as computer
professionals, to be an entrepreneur having innovative ideas and sound knowledge in various domains
leads to enthusiasm in higher studies and research.
Operating System (CD 405)
Course Outcomes
After Completing the course student should be able to:
CO1: Define the fundamental concepts of operating systems, including their functions, types, and
characteristics.
CO2: Apply file system concepts, disk organization, and directory structures. Evaluate and choose disk
allocation methods, and analyze disk scheduling algorithms
CO3: Implement CPU scheduling algorithms and comprehend memory management techniques,
including partitioning, swapping, segmentation, and paging. Apply the concept of virtual memory
through demand paging.
CO4: Design and construct solutions utilizing semaphores to manage concurrent processes effectively,
mitigating deadlock concerns.
CO5: Analyze case studies of Unix/Linux, Windows, and other network, distributed, and multiprocessor
operating systems to understand their architecture and functionalities.
Operating System (CD 405)
Laboratory Regulations and Safety Rules
The following Regulations and Safety Rules must be observed in all concerned laboratory locations.
1. It is the duty of all concerned parties who use any electrical laboratory to take all reasonable
steps to safeguard the HEALTH and SAFETY of themselves and all other users and visitors.
2. Make sure that all equipment is properly working before using it for laboratory exercises. Any
defective equipment must be reported immediately to the Lab. Instructors or Lab. Technical Staff.
3. Students are allowed to use only the equipment provided in the experiment manual or equipment
used for senior project laboratory.
4. Power supply terminals connected to any circuit are only energized with the presence of the
Instructor or Lab. Staff.
5. Students should keep a safe distance from the circuit breakers, electric circuits or any moving
parts during the experiment.
6. Avoid any part of your body to be connected to the energized circuit and ground.
7. Switch off the equipment and disconnect the power supplies from the circuit before leaving the
laboratory.
8. Observe cleanliness and proper laboratory housekeeping of the equipment and other related
accessories.
9. Wear proper clothes and safety gloves or goggles required in working areas that involve
fabrications of printed circuit boards, chemicals process control system, antenna communication
equipment and laser facility laboratories.
10. Double check your circuit connections specifically in handling electrical power machines, AC
motors and generators before switching “ON” the power supply.
11. Make sure that the last connection to be made in your circuit is the power supply and the first
thing to be disconnected is also the power supply.
12. Equipment should not be removed, transferred to any location without permission from the
laboratory staff.
13. Software installation in any computer laboratory is not allowed without the permission from the
Laboratory Staff.
14. Computer games are strictly prohibited in the computer laboratory.
15. Students are not allowed to use any equipment without proper orientation and actual hands on
equipment operation.
Operating System (CD 405)
INDEX
S.No. Name of the Program Date Signature
Implement the FCFS CPU scheduling algorithm
1 and demonstrate its process allocation.
Develop and demonstrate the SJF CPU scheduling
algorithm, highlighting its impact on process
2
completion time.
Construct and analyze the Priority CPU Scheduling
algorithm, showcasing how different priorities affect
3
scheduling.
Implement the Round Robin CPU scheduling
algorithm, and evaluate its effect on process
4
fairness and turnaround time.
Compare and evaluate various CPU scheduling
algorithms, emphasizing differences in turnaround
5
time and waiting time.
Design a solution for the Reader-Writers problem,
applying synchronization techniques to prevent data
6
inconsistency.
Develop a solution to the Dining Philosophers
7 problem, applying deadlock avoidance strategies
and analyzing outcomes.
Implement and compare various page replacement
8 algorithms, analyzing their impact on memory
management performance.
Develop and evaluate different Disk and Drum
9 scheduling algorithms, examining their efficiency in
disk utilization.
Operating System (CD 405)
Apply the Banker’s algorithm for deadlock
10 avoidance, evaluating its effectiveness in resource
allocation.
Operating System (CD 405)
Experiment 1: Implement the FCFS CPU scheduling algorithm and demonstrate its process allocation.
Program:
#include <stdio.h>
// Structure to represent a process
struct Process {
int id;
int arrival_time;
int burst_time;
int waiting_time;
int turnaround_time;
};
void fcfs_scheduling(struct Process processes[], int n) {
int current_time = 0;
int total_wait_time = 0;
int total_turnaround_time = 0;
printf("Process | Arrival Time | Burst Time | Waiting Time | Turnaround Time\n");
for (int i = 0; i < n; i++) {
// Calculate waiting time
if (current_time < processes[i].arrival_time) {
current_time = processes[i].arrival_time;
}
processes[i].waiting_time = current_time - processes[i].arrival_time;
processes[i].turnaround_time = processes[i].waiting_time + processes[i].burst_time;
// Update total times
total_wait_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;
// Update current time
current_time += processes[i].burst_time;
printf(" %d | %d | %d | %d | %d\n",
processes[i].id, processes[i].arrival_time, processes[i].burst_time,
processes[i].waiting_time, processes[i].turnaround_time);
}
// Calculate and display average times
double avg_wait_time = (double) total_wait_time / n;
double avg_turnaround_time = (double) total_turnaround_time / n;
printf("\nAverage Waiting Time: %.2f\n", avg_wait_time);
printf("Average Turnaround Time: %.2f\n", avg_turnaround_time);
}
Operating System (CD 405)
int main() {
// Input: List of processes with their IDs, arrival times, and burst times
struct Process processes[] = {
{1, 0, 5},
{2, 1, 3},
{3, 2, 8},
{4, 3, 6}
};
int n = sizeof(processes) / sizeof(processes[0]);
// Call the function to demonstrate FCFS scheduling
fcfs_scheduling(processes, n);
return 0;
}
Sample Output:
Process | Arrival Time | Burst Time | Waiting Time | Turnaround Time
1 | 0 | 5 | 0 | 5
2 | 1 | 3 | 4 | 7
3 | 2 | 8 | 7 | 15
4 | 3 | 6 | 13 | 19
Average Waiting Time: 6.00
Average Turnaround Time: 11.50
Operating System (CD 405)
Experiment 2: Develop and demonstrate the SJF CPU scheduling algorithm, highlighting its impact on
process completion time.
Program:
#include <stdio.h>
#include <stdbool.h>
// Structure to represent a process
struct Process {
int id;
int arrival_time;
int burst_time;
int waiting_time;
int turnaround_time;
bool completed;
};
void sjf_scheduling(struct Process processes[], int n) {
int completed = 0, current_time = 0;
int total_wait_time = 0, total_turnaround_time = 0;
printf("Process | Arrival Time | Burst Time | Waiting Time | Turnaround Time\n");
while (completed < n) {
int shortest = -1;
int min_burst = 1e9;
// Find the process with the shortest burst time that has arrived
for (int i = 0; i < n; i++) {
if (!processes[i].completed && processes[i].arrival_time <= current_time && processes[i].burst_time <
min_burst) {
min_burst = processes[i].burst_time;
shortest = i;
}
}
if (shortest == -1) {
// No process is ready to execute, increment time
current_time++;
continue;
}
// Process the selected process
processes[shortest].waiting_time = current_time - processes[shortest].arrival_time;
processes[shortest].turnaround_time = processes[shortest].waiting_time + processes[shortest].burst_time;
// Update total times
total_wait_time += processes[shortest].waiting_time;
total_turnaround_time += processes[shortest].turnaround_time;
// Update current time and mark process as completed
Operating System (CD 405)
current_time += processes[shortest].burst_time;
processes[shortest].completed = true;
completed++;
printf(" %d | %d | %d | %d | %d\n",
processes[shortest].id, processes[shortest].arrival_time, processes[shortest].burst_time,
processes[shortest].waiting_time, processes[shortest].turnaround_time);
}
// Calculate and display average times
double avg_wait_time = (double) total_wait_time / n;
double avg_turnaround_time = (double) total_turnaround_time / n;
printf("\nAverage Waiting Time: %.2f\n", avg_wait_time);
printf("Average Turnaround Time: %.2f\n", avg_turnaround_time);
}
int main() {
// Input: List of processes with their IDs, arrival times, and burst times
struct Process processes[] = {
{1, 0, 6, 0, 0, false},
{2, 1, 8, 0, 0, false},
{3, 2, 7, 0, 0, false},
{4, 3, 3, 0, 0, false}
};
int n = sizeof(processes) / sizeof(processes[0]);
// Call the function to demonstrate SJF scheduling
sjf_scheduling(processes, n);
return 0;
}
Sample Output:
Process | Arrival Time | Burst Time | Waiting Time | Turnaround Time
1 | 0 | 6 | 0 | 6
4 | 3 | 3 | 3 | 6
3 | 2 | 7 | 7 | 14
2 | 1 | 8 | 13 | 21
Average Waiting Time: 5.25
Average Turnaround Time: 11.75
Operating System (CD 405)
Experiment 3: Construct and analyze the Priority CPU Scheduling algorithm, showcasing how different
priorities affect scheduling.
Program:
#include <stdio.h>
#include <stdbool.h>
// Structure to represent a process
struct Process {
int id;
int arrival_time;
int burst_time;
int priority;
int waiting_time;
int turnaround_time;
bool completed;
};
void priority_scheduling(struct Process processes[], int n) {
int completed = 0, current_time = 0;
int total_wait_time = 0, total_turnaround_time = 0;
printf("Process | Arrival Time | Burst Time | Priority | Waiting Time | Turnaround Time\n");
while (completed < n) {
int highest_priority = -1;
int max_priority = -1;
// Find the process with the highest priority that has arrived
for (int i = 0; i < n; i++) {
if (!processes[i].completed && processes[i].arrival_time <= current_time && processes[i].priority >
max_priority) {
max_priority = processes[i].priority;
highest_priority = i;
}
}
if (highest_priority == -1) {
// No process is ready to execute, increment time
current_time++;
continue;
}
// Process the selected process
processes[highest_priority].waiting_time = current_time - processes[highest_priority].arrival_time;
processes[highest_priority].turnaround_time = processes[highest_priority].waiting_time +
processes[highest_priority].burst_time;
// Update total times
total_wait_time += processes[highest_priority].waiting_time;
Operating System (CD 405)
total_turnaround_time += processes[highest_priority].turnaround_time;
// Update current time and mark process as completed
current_time += processes[highest_priority].burst_time;
processes[highest_priority].completed = true;
completed++;
printf(" %d | %d | %d | %d | %d | %d\n",
processes[highest_priority].id, processes[highest_priority].arrival_time,
processes[highest_priority].burst_time,
processes[highest_priority].priority, processes[highest_priority].waiting_time,
processes[highest_priority].turnaround_time);
}
// Calculate and display average times
double avg_wait_time = (double) total_wait_time / n;
double avg_turnaround_time = (double) total_turnaround_time / n;
printf("\nAverage Waiting Time: %.2f\n", avg_wait_time);
printf("Average Turnaround Time: %.2f\n", avg_turnaround_time);
}
int main() {
// Input: List of processes with their IDs, arrival times, burst times, and priorities
struct Process processes[] = {
{1, 0, 6, 2, 0, 0, false},
{2, 1, 8, 1, 0, 0, false},
{3, 2, 7, 3, 0, 0, false},
{4, 3, 3, 4, 0, 0, false}
};
int n = sizeof(processes) / sizeof(processes[0]);
// Call the function to demonstrate Priority scheduling
priority_scheduling(processes, n);
return 0;
}
Operating System (CD 405)
Sample Output:
Process | Arrival Time | Burst Time | Priority | Waiting Time | Turnaround Time
3 | 2 | 7 | 3 | 5 | 12
4 | 3 | 3 | 4 | 2 | 5
1 | 0 | 6 | 2 | 0 | 6
2 | 1 | 8 | 1 | 7 | 15
Average Waiting Time: 3.50
Average Turnaround Time: 9.50
Operating System (CD 405)
Experiment 4: Implement the Round Robin CPU scheduling algorithm, and evaluate its effect on process
fairness and turnaround time
Program:
#include <stdio.h>
#include <stdbool.h>
// Structure to represent a process
struct Process {
int id;
int arrival_time;
int burst_time;
int remaining_time;
int waiting_time;
int turnaround_time;
};
void round_robin_scheduling(struct Process processes[], int n, int quantum) {
int current_time = 0, completed = 0;
int total_wait_time = 0, total_turnaround_time = 0;
printf("Process | Arrival Time | Burst Time | Waiting Time | Turnaround Time\n");
while (completed < n) {
bool progress = false;
for (int i = 0; i < n; i++) {
if (processes[i].remaining_time > 0 && processes[i].arrival_time <= current_time) {
progress = true;
if (processes[i].remaining_time > quantum) {
current_time += quantum;
processes[i].remaining_time -= quantum;
} else {
current_time += processes[i].remaining_time;
processes[i].waiting_time = current_time - processes[i].arrival_time - processes[i].burst_time;
processes[i].turnaround_time = processes[i].waiting_time + processes[i].burst_time;
total_wait_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;
processes[i].remaining_time = 0;
completed++;
printf(" %d | %d | %d | %d | %d\n",
processes[i].id, processes[i].arrival_time, processes[i].burst_time,
processes[i].waiting_time, processes[i].turnaround_time);
}
}
}
if (!progress) {
current_time++;
}
Operating System (CD 405)
}
// Calculate and display average times
double avg_wait_time = (double) total_wait_time / n;
double avg_turnaround_time = (double) total_turnaround_time / n;
printf("\nAverage Waiting Time: %.2f\n", avg_wait_time);
printf("Average Turnaround Time: %.2f\n", avg_turnaround_time);
}
int main() {
// Input: List of processes with their IDs, arrival times, and burst times
struct Process processes[] = {
{1, 0, 6, 6, 0, 0},
{2, 1, 8, 8, 0, 0},
{3, 2, 7, 7, 0, 0},
{4, 3, 3, 3, 0, 0}
};
int n = sizeof(processes) / sizeof(processes[0]);
int quantum = 4; // Time quantum
// Call the function to demonstrate Round Robin scheduling
round_robin_scheduling(processes, n, quantum);
return 0;
}
Sample Output:
Process | Arrival Time | Burst Time | Waiting Time | Turnaround Time
1 | 0 | 6 | 4 | 10
4 | 3 | 3 | 0 | 3
3 | 2 | 7 | 4 | 11
2 | 1 | 8 | 7 | 15
Average Waiting Time: 3.75
Average Turnaround Time: 9.75
Operating System (CD 405)
Experiment 5: Compare and evaluate various CPU scheduling algorithms, emphasizing differences in
turnaround time and waiting time.
Program:
#include <stdio.h>
#include <stdbool.h>
// Structure to represent a process
struct Process {
int id, arrival_time, burst_time, waiting_time, turnaround_time, remaining_time;
};
// Function to calculate averages and display results
void display_results(struct Process processes[], int n, int total_wait_time, int total_turnaround_time) {
printf("Process | Waiting Time | Turnaround Time\n");
for (int i = 0; i < n; i++) {
printf(" %d | %d | %d\n",
processes[i].id, processes[i].waiting_time, processes[i].turnaround_time);
}
printf("\nAverage Waiting Time: %.2f\n", (double)total_wait_time / n);
printf("Average Turnaround Time: %.2f\n", (double)total_turnaround_time / n);
}
// Function for FCFS scheduling
void fcfs_scheduling(struct Process processes[], int n) {
int current_time = 0, total_wait_time = 0, total_turnaround_time = 0;
for (int i = 0; i < n; i++) {
if (current_time < processes[i].arrival_time) current_time = processes[i].arrival_time;
processes[i].waiting_time = current_time - processes[i].arrival_time;
processes[i].turnaround_time = processes[i].waiting_time + processes[i].burst_time;
current_time += processes[i].burst_time;
total_wait_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;
}
printf("\nFCFS Scheduling:\n");
display_results(processes, n, total_wait_time, total_turnaround_time);
}
// Function for Round Robin scheduling
void round_robin_scheduling(struct Process processes[], int n, int quantum) {
int current_time = 0, completed = 0, total_wait_time = 0, total_turnaround_time = 0;
while (completed < n) {
for (int i = 0; i < n; i++) {
if (processes[i].remaining_time > 0) {
if (processes[i].remaining_time > quantum) {
current_time += quantum;
processes[i].remaining_time -= quantum;
Operating System (CD 405)
} else {
current_time += processes[i].remaining_time;
processes[i].waiting_time = current_time - processes[i].arrival_time - processes[i].burst_time;
processes[i].turnaround_time = processes[i].waiting_time + processes[i].burst_time;
total_wait_time += processes[i].waiting_time;
total_turnaround_time += processes[i].turnaround_time;
processes[i].remaining_time = 0;
completed++;
}
}
}
}
printf("\nRound Robin Scheduling:\n");
display_results(processes, n, total_wait_time, total_turnaround_time);
}
int main() {
struct Process processes[] = {{1, 0, 6, 0, 0, 6}, {2, 1, 8, 0, 0, 8}, {3, 2, 7, 0, 0, 7}, {4, 3, 3, 0, 0, 3}};
int n = sizeof(processes) / sizeof(processes[0]);
int quantum = 4;
fcfs_scheduling(processes, n);
// Reset remaining times for Round Robin Scheduling
for (int i = 0; i < n; i++) {
processes[i].remaining_time = processes[i].burst_time;
}
round_robin_scheduling(processes, n, quantum);
return 0;
}
Operating System (CD 405)
Sample Output:
Process 1: Arrival Time = 0, Burst Time = 6
Process 2: Arrival Time = 1, Burst Time = 8
Process 3: Arrival Time = 2, Burst Time = 7
Process 4: Arrival Time = 3, Burst Time = 3
FCFS Scheduling:
Process | Waiting Time | Turnaround Time
1 | 0 | 6
2 | 5 | 13
3 | 10 | 17
4 | 12 | 15
Average Waiting Time: 6.75
Average Turnaround Time: 12.75
Round Robin Scheduling:
Process | Waiting Time | Turnaround Time
1 | 4 | 10
2 | 6 | 14
3 | 8 | 15
4 | 3 | 6
Average Waiting Time: 5.25
Average Turnaround Time: 11.25
Operating System (CD 405)
Experiment 6: Design a solution for the Reader-Writers problem, applying synchronization techniques to
prevent data inconsistency.
Program:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// Shared data and synchronization primitives
int shared_data = 0; // The shared data being accessed
int reader_count = 0; // Number of active readers
pthread_mutex_t mutex; // Mutex for reader_count synchronization
pthread_mutex_t write_lock; // Lock to ensure writers exclusive access
// Reader function
void* reader(void* arg) {
int id = *(int*)arg;
free(arg);
pthread_mutex_lock(&mutex);
reader_count++;
if (reader_count == 1) {
pthread_mutex_lock(&write_lock); // First reader locks the writers
}
pthread_mutex_unlock(&mutex);
// Reading shared data
printf("Reader %d: Read shared data = %d\n", id, shared_data);
sleep(1); // Simulate read delay
pthread_mutex_lock(&mutex);
reader_count--;
if (reader_count == 0) {
pthread_mutex_unlock(&write_lock); // Last reader unlocks the writers
}
pthread_mutex_unlock(&mutex);
return NULL;
}
// Writer function
void* writer(void* arg) {
int id = *(int*)arg;
free(arg);
pthread_mutex_lock(&write_lock); // Writer gets exclusive access
// Writing to shared data
shared_data++;
printf("Writer %d: Updated shared data to %d\n", id, shared_data);
Operating System (CD 405)
sleep(2); // Simulate write delay
pthread_mutex_unlock(&write_lock);
return NULL;
}
int main() {
pthread_t readers[5], writers[2];
// Initialize mutexes
pthread_mutex_init(&mutex, NULL);
pthread_mutex_init(&write_lock, NULL);
// Create reader and writer threads
for (int i = 0; i < 5; i++) {
int* id = malloc(sizeof(int));
*id = i + 1;
pthread_create(&readers[i], NULL, reader, id);
}
for (int i = 0; i < 2; i++) {
int* id = malloc(sizeof(int));
*id = i + 1;
pthread_create(&writers[i], NULL, writer, id);
}
// Wait for all threads to finish
for (int i = 0; i < 5; i++) {
pthread_join(readers[i], NULL);
}
for (int i = 0; i < 2; i++) {
pthread_join(writers[i], NULL);
}
// Destroy mutexes
pthread_mutex_destroy(&mutex);
pthread_mutex_destroy(&write_lock);
printf("Reader-Writer simulation completed.\n");
return 0;
}
Sample Output:
Reader 1: Read shared data = 0
Reader 2: Read shared data = 0
Reader 3: Read shared data = 0
Writer 1: Updated shared data to 1
Reader 4: Read shared data = 1
Reader 5: Read shared data = 1
Writer 2: Updated shared data to 2
Operating System (CD 405)
Experiment 7: Develop a solution to the Dining Philosophers problem, applying deadlock avoidance strategies
and analyzing outcomes.
Program:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_PHILOSOPHERS 5
// Mutex array for forks
pthread_mutex_t forks[NUM_PHILOSOPHERS];
// Philosopher function
void* philosopher(void* arg) {
int id = *(int*)arg;
free(arg);
int left_fork = id; // Left fork index
int right_fork = (id + 1) % NUM_PHILOSOPHERS; // Right fork index
while (1) {
// Thinking
printf("Philosopher %d is thinking.\n", id);
sleep(1);
// Deadlock avoidance: Pick forks in a specific order
if (id % 2 == 0) {
// Even-numbered philosophers pick the left fork first
pthread_mutex_lock(&forks[left_fork]);
printf("Philosopher %d picked up left fork %d.\n", id, left_fork);
pthread_mutex_lock(&forks[right_fork]);
printf("Philosopher %d picked up right fork %d.\n", id, right_fork);
} else {
// Odd-numbered philosophers pick the right fork first
pthread_mutex_lock(&forks[right_fork]);
printf("Philosopher %d picked up right fork %d.\n", id, right_fork);
pthread_mutex_lock(&forks[left_fork]);
printf("Philosopher %d picked up left fork %d.\n", id, left_fork);
}
// Eating
printf("Philosopher %d is eating.\n", id);
sleep(2);
// Put down forks
pthread_mutex_unlock(&forks[left_fork]);
printf("Philosopher %d put down left fork %d.\n", id, left_fork);
Operating System (CD 405)
pthread_mutex_unlock(&forks[right_fork]);
printf("Philosopher %d put down right fork %d.\n", id, right_fork);
}
return NULL;
}
int main() {
pthread_t philosophers[NUM_PHILOSOPHERS];
// Initialize mutexes
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_mutex_init(&forks[i], NULL);
}
// Create philosopher threads
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
int* id = malloc(sizeof(int));
*id = i;
pthread_create(&philosophers[i], NULL, philosopher, id);
}
// Wait for threads to finish (this won't happen in this simulation)
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_join(philosophers[i], NULL);
}
// Destroy mutexes
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_mutex_destroy(&forks[i]);
}
return 0;
}
Operating System (CD 405)
Sample Output:
Philosopher 0 is thinking.
Philosopher 1 is thinking.
Philosopher 2 is thinking.
Philosopher 3 is thinking.
Philosopher 4 is thinking.
Philosopher 0 picked up left fork 0.
Philosopher 0 picked up right fork 1.
Philosopher 0 is eating.
Philosopher 1 picked up right fork 1.
Philosopher 1 picked up left fork 2.
Philosopher 1 is eating.
...
Philosopher 4 is thinking.
Philosopher 4 picked up right fork 4.
Philosopher 4 picked up left fork 0.
Philosopher 4 is eating.
Operating System (CD 405)
Experiment 8: Implement and compare various page replacement algorithms, analyzing their impact on
memory management performance
Program:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define PAGE_COUNT 10
// FIFO Page Replacement
int fifo_page_replacement(int pages[], int page_count, int frame_count) {
int frames[frame_count];
for (int i = 0; i < frame_count; i++) {
frames[i] = -1;
}
int page_faults = 0, index = 0;
for (int i = 0; i < page_count; i++) {
int page = pages[i];
int page_found = 0;
// Check if the page is already in the frames
for (int j = 0; j < frame_count; j++) {
if (frames[j] == page) {
page_found = 1;
break;
}
}
// If the page is not found, we have a page fault
if (!page_found) {
frames[index] = page;
index = (index + 1) % frame_count;
page_faults++;
}
}
return page_faults;
}
// Optimal Page Replacement
int optimal_page_replacement(int pages[], int page_count, int frame_count) {
int frames[frame_count];
for (int i = 0; i < frame_count; i++) {
frames[i] = -1;
}
int page_faults = 0;
Operating System (CD 405)
for (int i = 0; i < page_count; i++) {
int page = pages[i];
int page_found = 0;
// Check if the page is already in the frames
for (int j = 0; j < frame_count; j++) {
if (frames[j] == page) {
page_found = 1;
break;
}
}
// If page is not found, replace a page
if (!page_found) {
if (i < frame_count) {
frames[i] = page;
} else {
int farthest = -1;
int replace_index = -1;
// Find the page that will not be used for the longest time
for (int j = 0; j < frame_count; j++) {
int found = 0;
for (int k = i + 1; k < page_count; k++) {
if (frames[j] == pages[k]) {
found = 1;
break;
}
}
if (!found) {
replace_index = j;
break;
}
if (farthest < 0) {
farthest = i;
replace_index = j;
}
}
frames[replace_index] = page;
}
page_faults++;
}
}
return page_faults;
}
Operating System (CD 405)
// LRU Page Replacement
int lru_page_replacement(int pages[], int page_count, int frame_count) {
int frames[frame_count];
int last_used[frame_count];
for (int i = 0; i < frame_count; i++) {
frames[i] = -1;
last_used[i] = -1;
}
int page_faults = 0;
for (int i = 0; i < page_count; i++) {
int page = pages[i];
int page_found = 0;
// Check if the page is in the frames
for (int j = 0; j < frame_count; j++) {
if (frames[j] == page) {
page_found = 1;
last_used[j] = i;
break;
}
}
if (!page_found) {
int lru_index = -1;
int oldest = i;
for (int j = 0; j < frame_count; j++) {
if (frames[j] == -1) {
lru_index = j;
break;
} else if (last_used[j] < oldest) {
oldest = last_used[j];
lru_index = j;
}
}
frames[lru_index] = page;
last_used[lru_index] = i;
page_faults++;
}
}
return page_faults;
}
// LFU Page Replacement
int lfu_page_replacement(int pages[], int page_count, int frame_count) {
int frames[frame_count];
int frequency[frame_count];
for (int i = 0; i < frame_count; i++) {
frames[i] = -1;
Operating System (CD 405)
frequency[i] = 0;
}
int page_faults = 0;
for (int i = 0; i < page_count; i++) {
int page = pages[i];
int page_found = 0;
// Check if the page is in the frames
for (int j = 0; j < frame_count; j++) {
if (frames[j] == page) {
page_found = 1;
frequency[j]++;
break;
}
}
if (!page_found) {
int lfu_index = -1;
int min_freq = INT_MAX;
// Find the least frequently used page
for (int j = 0; j < frame_count; j++) {
if (frames[j] == -1) {
lfu_index = j;
break;
} else if (frequency[j] < min_freq) {
min_freq = frequency[j];
lfu_index = j;
}
}
frames[lfu_index] = page;
frequency[lfu_index] = 1;
page_faults++;
}
}
return page_faults;
}
// Main function to compare all algorithms
int main() {
// Sample page reference string
int pages[] = {7, 0, 1, 2, 0, 3, 0, 4, 2, 3};
int page_count = sizeof(pages) / sizeof(pages[0]);
int frame_count = 3;
// Call and compare each page replacement algorithm
int fifo_faults = fifo_page_replacement(pages, page_count, frame_count);
int optimal_faults = optimal_page_replacement(pages, page_count, frame_count);
Operating System (CD 405)
int lru_faults = lru_page_replacement(pages, page_count, frame_count);
int lfu_faults = lfu_page_replacement(pages, page_count, frame_count);
// Display results
printf("Page Reference String: ");
for (int i = 0; i < page_count; i++) {
printf("%d ", pages[i]);
}
printf("\n");
printf("FIFO Page Faults: %d\n", fifo_faults);
Sample Output:
Page Reference String: 7 0 1 2 0 3 0 4 2 3
FIFO Page Faults: 7
Optimal Page Faults: 6
LRU Page Faults: 7
LFU Page Faults: 6
Operating System (CD 405)
Experiment 9: Develop and evaluate different Disk and Drum scheduling algorithms, examining their
efficiency in disk utilization.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_REQUESTS 100
// FCFS Disk Scheduling Algorithm
int fcfs(int requests[], int n, int start) {
int total_seek_time = 0;
int current_position = start;
for (int i = 0; i < n; i++) {
total_seek_time += abs(current_position - requests[i]);
current_position = requests[i];
}
return total_seek_time;
}
// SSTF Disk Scheduling Algorithm
int sstf(int requests[], int n, int start) {
int total_seek_time = 0;
int current_position = start;
int visited[MAX_REQUESTS] = {0};
int count = 0;
while (count < n) {
int min_distance = INT_MAX;
int next_request = -1;
// Find the nearest request
for (int i = 0; i < n; i++) {
if (!visited[i]) {
int distance = abs(requests[i] - current_position);
if (distance < min_distance) {
min_distance = distance;
next_request = i;
}
}
}
visited[next_request] = 1;
total_seek_time += min_distance;
current_position = requests[next_request];
count++;
}
return total_seek_time;
Operating System (CD 405)
}
// SCAN Disk Scheduling Algorithm
int scan(int requests[], int n, int start, int max_track) {
int total_seek_time = 0;
int current_position = start;
// Sort the requests
int sorted_requests[MAX_REQUESTS];
for (int i = 0; i < n; i++) {
sorted_requests[i] = requests[i];
}
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (sorted_requests[j] > sorted_requests[j+1]) {
int temp = sorted_requests[j];
sorted_requests[j] = sorted_requests[j+1];
sorted_requests[j+1] = temp;
}
}
}
// Find position of current head
int i = 0;
while (i < n && sorted_requests[i] < current_position) {
i++;
}
// Move towards 0
for (int j = i-1; j >= 0; j--) {
total_seek_time += abs(current_position - sorted_requests[j]);
current_position = sorted_requests[j];
}
// Move towards max track
for (int j = i; j < n; j++) {
total_seek_time += abs(current_position - sorted_requests[j]);
current_position = sorted_requests[j];
}
return total_seek_time;
}
// C-SCAN Disk Scheduling Algorithm
int cscan(int requests[], int n, int start, int max_track) {
int total_seek_time = 0;
int current_position = start;
// Sort the requests
int sorted_requests[MAX_REQUESTS];
for (int i = 0; i < n; i++) {
Operating System (CD 405)
sorted_requests[i] = requests[i];
}
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (sorted_requests[j] > sorted_requests[j+1]) {
int temp = sorted_requests[j];
sorted_requests[j] = sorted_requests[j+1];
sorted_requests[j+1] = temp;
}
}
}
// Move towards max track
int i = 0;
while (i < n && sorted_requests[i] < current_position) {
i++;
}
for (int j = i; j < n; j++) {
total_seek_time += abs(current_position - sorted_requests[j]);
current_position = sorted_requests[j];
}
total_seek_time += (max_track - current_position); // jump to the other end of the disk
current_position = 0;
for (int j = 0; j < i; j++) {
total_seek_time += abs(current_position - sorted_requests[j]);
current_position = sorted_requests[j];
}
return total_seek_time;
}
// Main function to evaluate algorithms
int main() {
int requests[] = {98, 183, 41, 122, 14, 124, 65, 67};
int n = sizeof(requests) / sizeof(requests[0]);
int start = 53; // Starting position of the disk head
int max_track = 200; // Maximum number of tracks
printf("Disk Requests: ");
for (int i = 0; i < n; i++) {
printf("%d ", requests[i]);
}
printf("\n");
// FCFS Evaluation
int fcfs_seek_time = fcfs(requests, n, start);
printf("FCFS Seek Time: %d\n", fcfs_seek_time);
Operating System (CD 405)
// SSTF Evaluation
int sstf_seek_time = sstf(requests, n, start);
printf("SSTF Seek Time: %d\n", sstf_seek_time);
// SCAN Evaluation
int scan_seek_time = scan(requests, n, start, max_track);
printf("SCAN Seek Time: %d\n", scan_seek_time);
// C-SCAN Evaluation
int cscan_seek_time = cscan(requests, n, start, max_track);
printf("C-SCAN Seek Time: %d\n", cscan_seek_time);
return 0;
}
Sample Output:
Disk Requests: 98 183 41 122 14 124 65 67
FCFS Seek Time: 640
SSTF Seek Time: 236
SCAN Seek Time: 391
C-SCAN Seek Time: 436
Operating System (CD 405)
Experiment 10: Apply the Banker’s algorithm for deadlock avoidance, evaluating its effectiveness in resource
allocation.
Program:
#include <stdio.h>
#include <stdbool.h>
#define P 5 // Number of processes
#define R 3 // Number of resources
// Function to calculate Need matrix
void calculateNeed(int need[][R], int max[][R], int allocation[][R]) {
for (int i = 0; i < P; i++) {
for (int j = 0; j < R; j++) {
need[i][j] = max[i][j] - allocation[i][j];
}
}
}
// Function to check if the system is in a safe state
bool isSafe(int available[], int allocation[][R], int need[][R]) {
int work[R];
bool finish[P] = {false};
// Initialize work to Available
for (int i = 0; i < R; i++) {
work[i] = available[i];
}
int count = 0;
while (count < P) {
bool found = false;
// Find a process whose needs can be satisfied with the available resources
for (int p = 0; p < P; p++) {
if (!finish[p]) {
bool canFinish = true;
for (int i = 0; i < R; i++) {
if (need[p][i] > work[i]) {
canFinish = false;
break;
}
}
if (canFinish) {
// If the process can finish, simulate the release of resources
for (int i = 0; i < R; i++) {
work[i] += allocation[p][i];
}
finish[p] = true;
Operating System (CD 405)
count++;
found = true;
}
}
}
if (!found) {
return false; // If no process can proceed, the system is not in a safe state
}
}
return true; // All processes can finish, the system is in a safe state
}
// Function to request resources from a process
bool requestResources(int available[], int allocation[][R], int need[][R], int process, int request[]) {
// Check if request is valid
for (int i = 0; i < R; i++) {
if (request[i] > need[process][i]) {
printf("Error: Process has exceeded maximum claim.\n");
return false;
}
if (request[i] > available[i]) {
printf("Resources not available, process must wait.\n");
return false;
}
}
// Pretend to allocate the resources
for (int i = 0; i < R; i++) {
available[i] -= request[i];
allocation[process][i] += request[i];
need[process][i] -= request[i];
}
// Check if the system is still in a safe state
if (isSafe(available, allocation, need)) {
return true; // Safe state, request granted
} else {
// Rollback the changes as the state is unsafe
for (int i = 0; i < R; i++) {
available[i] += request[i];
allocation[process][i] -= request[i];
need[process][i] += request[i];
}
printf("Request denied, unsafe state.\n");
return false; // Unsafe state, request denied
}
}
int main() {
Operating System (CD 405)
int available[] = {3, 3, 2}; // Available resources
int max[][R] = {{7, 5, 3},
{3, 2, 2},
{9, 0, 2},
{2, 2, 2},
{4, 3, 3}}; // Maximum resource demand
int allocation[][R] = {{0, 1, 0},
{2, 1, 1},
{3, 2, 2},
{2, 1, 1},
{0, 0, 2}}; // Currently allocated resources
int need[P][R]; // Need matrix
calculateNeed(need, max, allocation);
printf("System is in a safe state: %s\n", isSafe(available, allocation, need) ? "Yes" : "No");
// Example request
int request[] = {1, 0, 2}; // Request by process 1 for resources
int process = 1;
printf("\nRequesting resources for Process %d: ", process);
if (requestResources(available, allocation, need, process, request)) {
printf("Request granted.\n");
} else {
printf("Request denied.\n");
}
return 0;
}
Sample Output:
System is in a safe state: Yes
Requesting resources for Process 1: Resources not available, process must wait.
Request denied.
Operating System (CD 405)