0% found this document useful (0 votes)
62 views50 pages

OS Lab Manual

Uploaded by

zeba.cs
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
62 views50 pages

OS Lab Manual

Uploaded by

zeba.cs
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 50

Department of Computer Science and Engineering

Submitted by

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 (CS 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 (CS 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 (CS 405)


Vision and Mission of the Department

Vision and Mission of the Department

Vision of the Department

Transforming the life of the graduates by providing excellent education in the field of Computer Science
& Engineering.

Mission of the Department

The department strives:

M1: Create student centric learning ambience so as to produce graduates who are well informed
about the latest technological trends and advancement in the world of computing, technology and
research.
M2: Produce professionals who are capable to work in diversified fields, find workable solutions to
complex problems with awareness and concern for society and environments.
M3: Continuously upgrade faculty through training so that they function effectively.
M4:Encourage industry institute collaborations through consultancies and research, helping students
to have conceptual learning.

Operating System (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 405)


INDEX

S.No. Name of the Program Date Signature

Implement the FCFS CPU scheduling algorithm and


1 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 fairness
4
and turnaround time.

Compare and evaluate various CPU scheduling


algorithms, emphasizing differences in turnaround
5
time and waiting time.

Create a program to solve the Producer-Consumer


problem, demonstrating effective inter-process
6
communication.

Design a solution for the Reader-Writers problem,


applying synchronization techniques to prevent data
7
inconsistency.

Develop a solution to the Dining Philosophers


8 problem, applying deadlock avoidance strategies and
analyzing outcomes.

Operating System (CS 405)


Implement and compare various page replacement
9 algorithms, analyzing their impact on memory
management performance.

Develop and evaluate different Disk and Drum


10 scheduling algorithms, examining their efficiency in
disk utilization.

Apply the Banker’s algorithm for deadlock avoidance,


11
evaluating its effectiveness in resource allocation.
Implement Remote Procedure Call (RPC),
demonstrating client-server communication in
12
distributed systems.

Design and develop a basic device driver for a


13 specified device or peripheral, demonstrating
hardware-software interaction principles.

Operating System (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 405)


Experiment 6: Create a program to solve the Producer-Consumer problem, demonstrating effective
inter-process communication.

Program:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

#define BUFFER_SIZE 5 // Size of the buffer

int buffer[BUFFER_SIZE];
int count = 0; // Number of items in the buffer

pthread_mutex_t mutex; // Mutex lock for buffer synchronization


pthread_cond_t cond; // Condition variable for signaling

// Producer function
void* producer(void* arg) {
for (int i = 0; i < 10; i++) { // Produce 10 items
pthread_mutex_lock(&mutex);

// Wait if the buffer is full


while (count == BUFFER_SIZE) {
pthread_cond_wait(&cond, &mutex);
}

// Produce an item and add to buffer


buffer[count] = rand() % 100;
printf("Producer: Produced item %d at index %d\n", buffer[count], count);
count++;

// Signal the consumer


pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

sleep(1); // Simulate production time


}
return NULL;
}

// Consumer function
void* consumer(void* arg) {
for (int i = 0; i < 10; i++) { // Consume 10 items
pthread_mutex_lock(&mutex);

// Wait if the buffer is empty


while (count == 0) {
pthread_cond_wait(&cond, &mutex);
}
Operating System (CS 405)
// Consume an item from the buffer
count--;
printf("Consumer: Consumed item %d from index %d\n", buffer[count], count);

// Signal the producer


pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

sleep(2); // Simulate consumption time


}
return NULL;
}

int main() {
pthread_t producer_thread, consumer_thread;

// Initialize mutex and condition variable


pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);

// Create producer and consumer threads


pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);

// Wait for the threads to finish


pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);

// Destroy mutex and condition variable


pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);

printf("Producer-Consumer simulation completed.\n");


return 0;
}

Operating System (CS 405)


Sample Output:
Producer: Produced item 45 at index 0
Consumer: Consumed item 45 from index 0
Producer: Produced item 38 at index 0
Consumer: Consumed item 38 from index 0
Producer: Produced item 72 at index 0
Consumer: Consumed item 72 from index 0
Producer: Produced item 50 at index 0
Consumer: Consumed item 50 from index 0
Producer: Produced item 97 at index 0
Consumer: Consumed item 97 from index 0
Producer: Produced item 59 at index 0
Consumer: Consumed item 59 from index 0
Producer: Produced item 14 at index 0
Consumer: Consumed item 14 from index 0
Producer: Produced item 61 at index 0
Consumer: Consumed item 61 from index 0
Producer: Produced item 28 at index 0
Consumer: Consumed item 28 from index 0
Producer: Produced item 39 at index 0
Consumer: Consumed item 39 from index 0
Producer-Consumer simulation completed.

Operating System (CS 405)


Experiment 7: 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 (CS 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 (CS 405)
Experiment 8: 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 (CS 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 (CS 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 (CS 405)


Experiment 9: 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 (CS 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 (CS 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 (CS 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 (CS 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 (CS 405)


Experiment 10: 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 (CS 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 (CS 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 (CS 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 (CS 405)


Experiment 11: 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 (CS 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 (CS 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 (CS 405)


Experiment 12: Implement Remote Procedure Call (RPC), demonstrating client-server communication in
distributed systems

Program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>

#define PORT 8080


#define MAX_BUF 1024

// Function to perform the remote procedure (addition)


int add(int a, int b) {
return a + b;
}

// Server thread function


void* server_thread(void* arg) {
int server_fd, new_socket;
struct sockaddr_in address;
char buffer[MAX_BUF];
int valread;

// Create socket
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

// Bind the socket to the address and port


if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}

// Start listening for incoming connections


if (listen(server_fd, 3) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}

printf("Server listening on port %d...\n", PORT);

Operating System (CS 405)


// Accept incoming connections
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&(int){0})) < 0) {
perror("Accept failed");
exit(EXIT_FAILURE);
}

// Receive data from the client


valread = read(new_socket, buffer, MAX_BUF);
if (valread < 0) {
perror("Read failed");
exit(EXIT_FAILURE);
}

// Extract the two integers from the received message


int a, b;
sscanf(buffer, "%d %d", &a, &b);

// Perform the remote procedure (addition)


int result = add(a, b);

// Send the result back to the client


snprintf(buffer, MAX_BUF, "Result: %d", result);
send(new_socket, buffer, strlen(buffer), 0);
printf("Result sent to client: %d\n", result);

// Close the connection


close(new_socket);
close(server_fd);
return NULL;
}

// Client function
void client_function() {
int sock = 0;
struct sockaddr_in server_address;
char buffer[MAX_BUF];

// Create socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}

server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary form


if (inet_pton(AF_INET, "127.0.0.1", &server_address.sin_addr) <= 0) {
perror("Invalid address/Address not supported");
exit(EXIT_FAILURE);
}
Operating System (CS 405)
// Connect to the server
if (connect(sock, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {
perror("Connection failed");
exit(EXIT_FAILURE);
}

// Input two integers from the user


int a, b;
printf("Enter two integers to add: ");
scanf("%d %d", &a, &b);

// Send data (two integers) to the server


snprintf(buffer, MAX_BUF, "%d %d", a, b);
send(sock, buffer, strlen(buffer), 0);

// Read the result from the server


int valread = read(sock, buffer, MAX_BUF);
if (valread < 0) {
perror("Read failed");
exit(EXIT_FAILURE);
}

printf("Received from server: %s\n", buffer);

// Close the socket


close(sock);
}

int main() {
pthread_t server_tid;

// Start the server thread


pthread_create(&server_tid, NULL, server_thread, NULL);

// Wait for the server to set up and then run the client
sleep(1); // Give the server a second to start

// Run the client function


client_function();

// Wait for the server thread to finish


pthread_join(server_tid, NULL);

return 0;
}

Operating System (CS 405)


Sample Output:

Server listening on port 8080...


Result sent to client: 15

Enter two integers to add: 7 8


Received from server: Result: 15

Operating System (CS 405)


Experiment 13: Design and develop a basic device driver for a specified device or peripheral, demonstrating
hardware-software interaction principles

Program:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "simple_device" // Device name


#define DEVICE_MAJOR 0 // Major number (0 for dynamic allocation)
#define BUFFER_SIZE 256 // Buffer size for the device

static int device_open = 0; // Device open flag


static char device_buffer[BUFFER_SIZE]; // Buffer to store data
static struct cdev simple_cdev; // Char device structure

// Device open function


static int device_open_func(struct inode *inode, struct file *file) {
if (device_open) {
printk(KERN_ALERT "Device is already open.\n");
return -EBUSY; // Device already in use
}

device_open = 1;
try_module_get(THIS_MODULE); // Increment module usage count
printk(KERN_INFO "Device opened successfully.\n");
return 0;
}

// Device release function


static int device_release_func(struct inode *inode, struct file *file) {
device_open = 0;
module_put(THIS_MODULE); // Decrement module usage count
printk(KERN_INFO "Device closed successfully.\n");
return 0;
}

// Device read function


static ssize_t device_read_func(struct file *file, char __user *buf, size_t len, loff_t *offset) {
int bytes_read = 0;

if (*offset >= BUFFER_SIZE) {


return 0; // End of buffer reached
}

while (len && *offset < BUFFER_SIZE) {


put_user(device_buffer[*offset], buf++);
Operating System (CS 405)
len--;
bytes_read++;
(*offset)++;
}

printk(KERN_INFO "Sent %d bytes to user space.\n", bytes_read);


return bytes_read;
}

// Device write function


static ssize_t device_write_func(struct file *file, const char __user *buf, size_t len, loff_t *offset) {
int bytes_written = 0;

while (len && *offset < BUFFER_SIZE) {


get_user(device_buffer[*offset], buf++);
len--;
bytes_written++;
(*offset)++;
}

printk(KERN_INFO "Received %d bytes from user space.\n", bytes_written);


return bytes_written;
}

// File operations structure


static struct file_operations fops = {
.owner = THIS_MODULE,
.open = device_open_func,
.release = device_release_func,
.read = device_read_func,
.write = device_write_func,
};

// Module initialization function


static int __init simple_device_init(void) {
int result;
dev_t devno = MKDEV(DEVICE_MAJOR, 0); // Dynamic major allocation

// Register the device with the kernel


if ((result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME)) < 0) {
printk(KERN_ALERT "Failed to register character device\n");
return result;
}

// Initialize the cdev structure


cdev_init(&simple_cdev, &fops);
simple_cdev.owner = THIS_MODULE;

// Add the device to the kernel


if ((result = cdev_add(&simple_cdev, devno, 1)) < 0) {
unregister_chrdev_region(devno, 1);
Operating System (CS 405)
printk(KERN_ALERT "Failed to add character device\n");
return result;
}

printk(KERN_INFO "Simple device driver initialized successfully.\n");


return 0;
}

// Module exit function


static void __exit simple_device_exit(void) {
dev_t devno = MKDEV(DEVICE_MAJOR, 0);
cdev_del(&simple_cdev); // Remove the device
unregister_chrdev_region(devno, 1); // Unregister the device
printk(KERN_INFO "Simple device driver unloaded successfully.\n");
}

module_init(simple_device_init);
module_exit(simple_device_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver for hardware interaction.");

Sample Output:

The results are verified under experimental error considerations.

Operating System (CS 405)

You might also like