[go: up one dir, main page]

0% found this document useful (0 votes)
48 views43 pages

Final Os Lab Manual M.tech - Cse

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)
48 views43 pages

Final Os Lab Manual M.tech - Cse

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/ 43

EXCEL ENGINEERING COLLEGE (AUTONOMOUS)

KOMARAPALAYAM-637 303

DEPARTMENT OF

M.TECH-COMPUTER SCIENCE AND ENGINEERING

III Semester

23MCS305- OPERATING SYSTEM LABORATORY

LABORATORY MANUAL
ENGINEERING COLLEGE (AUTONOMOUS)

KOMARAPALAYAM-637 303

DEPARTMENT OF

M.TECH - COMPUTER SCIENCE AND ENGINEERING

LABORATORY RECORD NOTEBOOK

This is to certify that bonafide record of work done by

Register No. _____ ____ IIIrd semester M. Tech - Computer Science and
Engineering branch during the year 2024-2025 in the _________________
_____
Laboratory.

Staff In-charge Head of Department

Submitted for the Practical Examination held on:

Internal Examiner External Examiner


LIST OF EXPERIMENTS

1 DEVELOP PROGRAMS FOR PROCESS CREATION AND COMMUNICATION.

a. Write simple shell programs.

b. Creation of process and child process

c. Demonstration of inter-process communication

d. Creation of Zombie and Orphan process

e. Creation of threads

2
SIMULATION OF THE CPU SCHEDULING ALGORITHMS

3
DEMONSTRATION OF SEMAPHORES

4
IMPLEMENTATION OF PRODUCER-CONSUMER PROBLEM

5
SIMULATION OF BANKERS ALGORITHM FOR DEADLOCK AVOIDANCE

6
CREATION OF VIRTUAL MACHINE IN A HYPERVISOR
Exp No:1 DEVELOP PROGRAMS FOR PROCESS
CREATION AND COMMUNICATION.
Date:

a. Write simple shell programs.

b. Creation of process and child process

c. Demonstration of inter-process communication

d. Creation of Zombie and Orphan process

e. Creation of threads

A.WRITE SIMPLE SHELL PROGRAMS.

AIM:
To create a simple command-line shell that can accept and execute user commands.

PROBLEM DESCRIPTION:

You are required to implement a simple command-line shell program in C (or any language
of your choice). The shell should provide the following functionalities:

FUNCTIONAL REQUIREMENTS:

1. Command Input:
o The shell should prompt the user for input, where the user can enter a
command.
o The shell should read a line of input and parse it into individual commands
and arguments.
2. Command Execution:
o The shell should be able to execute built-in commands (like cd, exit, and
help) directly.
o For other commands, the shell should create a child process using fork() and
use exec() to run the command.
o The shell should wait for the child process to finish before displaying the
prompt again.
3. Built-in Commands:
o Implement at least the following built-in commands:
 cd [directory]: Change the current working directory.
 exit: Terminate the shell.
 help: Display a help message listing available commands.
4. Error Handling:
o Handle errors gracefully (e.g., if a command is not found, print an error
message).
o Ensure that invalid inputs are managed properly.
5. Command History (Optional):
o Implement a simple command history feature that stores the last few
commands entered by the user and allows the user to recall them using a
specific command (e.g., history).
6. Background Processes (Optional):
o Allow users to run commands in the background by appending & at the end
of the command. The shell should not wait for these processes to finish.

ALGORITHM:

1. Display a prompt to the user.


2. Read the user input.
3. Remove the newline character from the input.
4. If the user inputs "exit," terminate the shell.
5. Use the system() function to execute the command.
6. Repeat steps 1-5.

PROGRAM:

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

#define MAX_CMD_LEN 100

int main() {
char cmd[MAX_CMD_LEN];

while (1) {
printf("simple_shell> ");
if (!fgets(cmd, MAX_CMD_LEN, stdin)) break;

// Remove newline character


cmd[strcspn(cmd, "\n")] = 0;

if (strcmp(cmd, "exit") == 0) {
break;
}
system(cmd);
}
return 0;
}
OUTPUT:

simple_shell> ls
file1.txt file2.txt
simple_shell> echo "Hello World"
Hello World
simple_shell> exit

RESULT:

The shell can execute any command available in the system and responds to user inputs
until "exit" is entered.
B.CREATION OF PROCESS AND CHILD PROCESS

AIM:
To demonstrate the creation of a child process using fork().

PROBLEM DESCRIPTION:

You are tasked with writing a program that demonstrates the creation and management of
processes in a Unix-like operating system. The program should create child processes and
communicate between the parent and child using pipes.

FUNCTIONAL REQUIREMENTS:

1. Process Creation:
o Use the fork() system call to create at least two child processes from a parent
process.
2. Process Communication:
o Implement a pipe using pipe() to allow communication between the parent
and child processes. The parent should send a message to the child process
via the pipe.
3. Message Handling:
o The parent process will send a predefined message to the first child process.
o The first child process should modify the message (e.g., convert it to
uppercase) and then send it to the second child process.
o The second child process should print the received message to the console.
4. Process Termination:
o The parent process should wait for both child processes to complete before
terminating itself.
o Ensure that appropriate exit statuses are checked.
5. Error Handling:
o Handle errors for system calls like fork(), pipe(), and write(). If any call fails,
print an error message and exit the program gracefully.

ALGORITHM:

1. Call fork() to create a new process.


2. Check the return value:
o If it’s less than zero, report an error.
o If it’s zero, execute the child code.
o If it’s greater than zero, execute the parent code and print both PIDs.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
pid_t pid = fork();

if (pid < 0) {
perror("Fork failed");
exit(1);
} else if (pid == 0) {
// Child process
printf("I am the child process (PID: %d)\n", getpid());
} else {
// Parent process
printf("I am the parent process (PID: %d), my child is (PID: %d)\n", getpid(),
pid);
}
return 0;}

OUTPUT:

simple_shell> ls
file1.txt file2.txt
simple_shell> echo "Hello World"
Hello World
simple_shell> exit

RESULT:

The program successfully creates a child process, and both processes execute their
respective code.
C.DEMONSTRATION OF INTER-PROCESS COMMUNICATION

AIM:
To demonstrate inter-process communication using a pipe.

PROBLEM DESCRIPTION:

You are required to create a program that demonstrates inter-process communication using
shared memory and semaphores. The program will consist of a parent process and two
child processes that communicate with each other through shared memory, synchronized
using semaphores.

FUNCTIONAL REQUIREMENTS:

1. Shared Memory Setup:


o Use the shm get() and sh mat() system calls to create and attach shared
memory segments that can be accessed by both child processes.
2. Semaphore Initialization:
o Use POSIX semaphores ( sem_ open(), sem_ wait(), sem_ post()) to
synchronize access to the shared memory.
o Initialize two semaphores: one for controlling access to the shared memory
for writing (by the parent) and another for reading (by the child).
3. Process Creation:
o Create two child processes using fork() from the parent process.
4. Communication Logic:
o The parent process should write a message into the shared memory.
o The first child process should read the message, modify it (e.g., append
additional text), and write it back to the shared memory.
o The second child process should read the modified message from the shared
memory and print it to the console.
5. Cleanup:
o After all processes have completed their tasks, the parent process should
clean up by detaching and deleting the shared memory segment and
semaphores.
6. Error Handling:
o Handle errors for system calls like shmget(), shmat(), sem_open(), and
others. If any call fails, print an error message and exit the program
gracefully.
ALGORITHM:

1. Create a pipe using pipe().


2. Call fork() to create a child process.
3. In the child process, read from the pipe.
4. In the parent process, write a message to the pipe.
5. Close the pipe ends appropriately.

PROGRAM:

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

int main() {
int fd[2];
pid_t pid;
char buffer[20];

if (pipe(fd) == -1) {
perror("Pipe failed");
exit(1);
}
pid = fork();
if (pid < 0) {
perror("Fork failed");
exit(1);
} else if (pid == 0) {
// Child process
close(fd[1]); // Close write end
read(fd[0], buffer, size of(buffer));
printf("Child received: %s\n", buffer);
close(fd[0]);
} else {
// Parent process
close(fd[0]); // Close read end
const char *msg = "Hello from parent";
write(fd[1], msg, strlen(msg) + 1);
close(fd[1]); // Close write end
}

return 0;
}
OUTPUT:

Child received: Hello from parent

RESULT:
The child process successfully receives a message from the parent process via the pipe.
D.CREATION OF ZOMBIE AND ORPHAN PROCESS

AIM:
To illustrate the creation of zombie and orphan processes.

PROBLEM DESCRIPTION:

You are tasked with writing a program that demonstrates the concepts of zombie and
orphan processes in a Unix-like operating system. The program should create child
processes that exhibit these behaviors, allowing you to observe and understand how
process states change.

FUNCTIONAL REQUIREMENTS:

1. Zombie Process Creation:


o Create a child process using fork().
o In the child process, make it exit immediately using _exit(). This will leave
the child in a "zombie" state since the parent process will not call wait() to
collect its termination status.
o Add a delay in the parent process (using sleep()) before it exits, allowing you
to observe the zombie state.
2. Orphan Process Creation:
o Create another child process that will run for a short duration and then exit.
Before the child exits, the parent process should exit first (using _exit()),
making the child an orphan process.
o Use get ppid() in the child process to print the parent’s PID before it exits,
allowing you to see that the child process has been re-parented to the init
process (PID 1).
3. Process Management:
o Use the ps command or similar tools to observe the state of the processes
(zombie and orphan) during and after execution.
4. Error Handling:
o Handle errors gracefully when calling fork() and other system calls. If any
call fails, print an error message and exit the program.

ZOMBIE PROCESS:

1. Create a child process using fork().


2. In the child, exit immediately.
3. In the parent, sleep for a while to allow the child to become a zombie.
PROGRAM:

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

int main() {
pid_t pid = fork();

if (pid > 0) {
// Parent process
printf("Parent process (PID: %d) sleeping for 10 seconds...\n", getpid());
sleep(10); // Sleep to allow child to become a zombie
} else if (pid == 0) {
// Child process
printf("Child process (PID: %d) exiting...\n", get pid());
exit(0);
} else {
P error("Fork failed");
}

return 0;
}

OUTPUT:

Parent process (PID: 1234) sleeping for 10 seconds... Child process (PID: 1235)
exiting...

RESULT:
The child process becomes a zombie, waiting for the parent to call wait().
E. CREATION OF THREADS

AIM:
To demonstrate the creation of multiple threads using POSIX threads.

PROBLEM DESCRIPTION:

You are tasked with writing a multithreaded program that demonstrates the creation and
management of threads using a threading library (such as p threads in C). The program will
create multiple threads that perform specific tasks concurrently.

FUNCTIONAL REQUIREMENTS:

1. Thread Creation:
o Use the appropriate threading library to create at least three threads. Each
thread should execute a separate function.
2. Thread Functions:
o Implement the following thread functions:
 Thread 1: Calculate and print the sum of the first N natural numbers.
 Thread 2: Calculate and print the factorial of a given number.
 Thread 3: Print the Fibonacci series up to the N-th term.
3. Data Sharing:
o Use a shared variable or data structure to store results from each thread.
o Ensure that access to the shared data is synchronized using mutexes to
prevent race conditions.
4. Thread Joining:
o After creating the threads, use p thread_ join() (or equivalent) to ensure that
the main thread waits for all child threads to complete before exiting.
5. Error Handling:
o Handle errors appropriately for thread creation and joining. If any call fails,
print an error message and exit the program gracefully.
6. User Input (Optional):
o Allow the user to input values for N (for sum, factorial, and Fibonacci)
before the threads are created.

ALGORITHM:

1. Define a thread function that prints a message.


2. Create an array of threads.
3. Use pthread_create() to start multiple threads.
4. Use pthread_join() to wait for all threads to finish.
PROGRAM:

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

int main() {

# Define the thread function

def thread_ function(name):

print(f' Thread {name}: starting')

time. sleep(2) # Simulate some work

print(f' Thread {name}: finishing')

# Create threads

threads = []

for index in range(3):

thread = threading. Thread(target=thread_ function, args=(index,))

threads. append(thread)

thread. start()

# Wait for all threads to complete

for thread in threads:

thread. join()

print('All threads finished.')

}
OUTPUT:

Thread 0: starting

Thread 1: starting

Thread 2: starting

Thread 0: finishing

Thread 1: finishing

Thread 2: finishing

All threads finished.

RESULT:
the creation of multiple threads using POSIX threads are succesfully.
Exp No:2 SIMULATION OF THE CPU SCHEDULING
ALGORITHMS
Date:

AIM:

To implement FCFS, SJF, Priority and Round robin scheduling algorithms using C.

PROBLEM DESCRIPTION:

FIRST COME FIRST SERVE SCHEDULING:

With this scheme, the process that requests the CPU first is allocated the CPU first.
The implementation of the FCFS policy is easily managed with a FIFO queue. The FCFS
scheduling algorithm is non preemptive. Once the CPU has been allocated to a process,
that
process keeps the CPU until it releases the CPU either by terminating or by requesting I/O.
While considering the performance of the FCFS scheduling algorithm, the higher burst
time
process makes the lower burst time process to wait for a long time. This effect is known as
convoy effect.

SHORTEST JOB FIRST SCHEDULING:

This algorithm associates with each process the length of the latter’s next CPU burst.
When the CPU is available, it is assigned to the process that has the smallest next CPU
burst.
If two processes have the same length next CPU burst, FCFS scheduling is used to break
the
tie. The SJF algorithm may be either preemptive or non preemptive. The choice arises
when a
new process arrives at the ready queue while a previous process is executing. The SJF
scheduling algorithm is provably optimal, in that it gives the minimum average waiting
time
for a given set of processes.

PRIORITY SCHEDULING:

A priority is associated with each process and the CPU is allocated to the process with
the highest priority. Equal priority processes are scheduled in FCFS order. An SJF
algorithm
is simply a priority algorithm where the priority(p) is the inverse of the next CPU burst.
The
larger the CPU burst, the lower the priority and vice versa.
ROUND-ROBIN SCHEDULING:

The round-robin scheduling algorithm is designed especially for time-sharing systems.


It is similar to FCFS scheduling, but preemption is added to switch between processes. A
small unit of time, called a time quantum is defined. A time quantum is generally from 10
to
100 milli seconds. The ready queue is treated as circular queue.

1.FCFS:

ALGORITHM:

1: Get the number of processes and burst time.


2: The process is executed in the order given by the user.
3: Calculate the waiting time and turn around time.
4: Display the gantt chart, avg waiting time and turn around time

PROGRAM:

#include&lt;stdio.h&gt;
void main(int argc,char *argv[])
{
int i,j=0,n,burst[10],wait[10],turn[10];
float w=0,t=0;
printf(&quot;Enter the no. of processes& quot;);
scanf(&quot;%d&quot;,&amp;n);
burst[0]=0;
printf(&quot;Enter the burst time& quot;);
for(i=1;i&lt;=n;i++)
{
scanf(&quot;%d&quot;,&amp; burst[i]);
}
printf(&quot;\n\nGantt chart\n& quot;);
printf(&quot;\n \n&quot;);
for(i=1;i&lt;=n;i++)
printf(&quot;\tP%d\t|&quot;,i);
printf(&quot;\n \n&quot;);
for(i=0;i&lt;=n;i++)
{
j=j+burst[i];
wait[i+1]=j;
turn[i]=j;
printf(&quot;%d\t\t&quot;,j);
}
for(i=1;i&lt;=n;i++)
w=w+wait[i];
for(i=0;i&lt;=n;i++)
t=t+turn[i];
w=w/n;
t=t/n;
printf(&quot;\n Average waiting time %0.2f&quot;,w);
printf(&quot;\n Average turn around time %0.2f&quot;,t);
}

OUTPUT:

cc fcfs.c./a.out
Enter the no. of processes 3
Enter the burst time 3 6 8
Gantt chart
P1 | P2 | P3 |
0 3 9 17
Average waiting time 4.00
Average turn around time 9.67

2.SJF:

ALGORITHM:

1: Get the number of processes and burst time.


2: Sort the process based on the burst time in ascending order.
3: Calculate the waiting time and turnaround time.
4: Display the gantt chart, avg waiting time and turnaround time.

PROGRAM:

#include&lt;stdio.h&gt;
void main(int argc,char *argv[])
{
int b[10],temp,i,j,n,wait[10],burst[10],turn[10];
float w=0,t=0;
printf(&quot;Enter the no. of processes&quot;);
scanf(&quot;%d&quot;,&amp;n);
burst[0]=0;
b[0]=0;
printf(&quot;Enter the burst time&quot;);
for(i=1;i&lt;=n;i++)
{
scanf(&quot;%d&quot;,&amp;burst[i]);
}
for(i=1;i&lt;=n;i++)
b[i]=burst[i];
for(i=1;i&lt;n;i++)
for(j=i+1;j&lt;=n;j++)
if(b[i]&gt;b[j])
{
temp=b[i];
b[i]=b[j];
b[j]=temp;
}
printf(&quot;\nGantt chart&quot;);
printf(&quot;\n \n&quot;);
for(i=1;i&lt;=n;i++)
for(j=1;j&lt;=n;j++)
if(b[i]==b[j])
printf(&quot;P%d|\t&quot;,j);
printf(&quot;\n \n&quot;);
j=0;
for(i=0;i&lt;=n;i++)
{
j=j+b[i];
wait[i+1]=j;
turn[i]=j;
printf(&quot;%d\t&quot;,j);

}
for(i=1;i&lt;=n;i++)
w=w+wait[i];
for(i=0;i&lt;=n;i++)
t=t+turn[i];
w=w/n;
t=t/n;
printf(&quot;\n Average waiting time is %0.2f&quot;,w);
printf(&quot;\n Average turn around time is %0.2f&quot;,t);
}

OUTPUT:

cc sjf.c
./a.out
Enter the no. of processes 3
Enter the burst time2 1 3
Gantt chart
P1| P2| P3|
0136
Average waiting time is 1.33
Average turn around time is 3.33

3) PRIORITY SCHEDULING ALGORITHM:

1: Get the number of processes, priority and burst time.


2: Sort the process based on the priority in ascending order
3: Calculate the waiting time and turnaround time.
4: Display the gantt chart, avg waiting time and turnaround time.

PROGRAM:

#include&lt;stdio.h&gt;
void main(int argc,char *argv[])
{
int temp,i,n,j,p[10],burst[10],b[10],wait[10],turn[10],b1[10],p1[10];
float w=0,t=0;
printf(&quot;Enter the number of processes& quot;);
scanf(&quot;%d&quot;,&amp;n);
burst[0]=0;
for(i=1;i&lt;=n;i++)
{
printf(&quot;Enter the Burst Time and Priority&quot;);
scanf(&quot;%d%d&quot;,&amp;b1[i],&amp;p[i]);
}
for(i=1;i&lt;=n;i++)
p1[i]=p[i];
for(j=1;j&lt;=n;j++)

p1[j]=p[j];
for(i=1;i&lt;=n;i++)
for(j=i+1;j&lt;=n;j++)
if(p[i]&gt;p[j])
{
temp=p[i];
p[i]=p[j];
p[j]=temp;
temp=b[i];
b[i]=b[j];
b[j]=temp;
}
for(i=1;i&lt;=n;i++)
printf(&quot;%d&quot;,p[i]);
printf(&quot;\n\t\t\tGanttChart\n&quot;);
printf(&quot;\t \n&quot;);
for(i=1;i&lt;=n;i++)
for(j=1;j&lt;=n;j++)
if(p[i]==p1[j])
{
b[i]=b1[j];
printf(&quot;\t\tp%d&quot;,j);
}
printf(&quot;\t\n\t \n\t&quot;);
j=0;
for(i=0;i&lt;=n;i++)
{
j=j+b[i];
wait[i+1]=j;
turn[i]=j;
printf(&quot;%d\t\t&quot;,j);
}
for(i=1;i&lt;=n;i++)
t=t+turn[i];
w=w+wait[i];
w=w/n;
t=t/n;
printf(&quot;\n The average Waiting Time %f& quot;, w);
printf(&quot;\n The average Turnaround Time %f& quot;, t);
}

OUTPUT:

cc pri.c
./a.out
Enter the number of processes 3
Enter the Burst Time and Priority 2 3
Enter the Burst Time and Priority 2 1
Enter the Burst Time and Priority 4 2
Gantt Chart
p2 p3 p1
0268
The average Waiting Time 2.666667
The average Turnaround Time 5.333333

4. RR SCHEDULING:

ALGORITHM:

1: Initialize all the structure elements


2: Receive inputs from the user to fill process id, burst time and arrival time.
3: Calculate the waiting time for all the process id.
i) The waiting time for first instance of a process is calculated as:
a[i].wait time=count + a[i].arrivt
ii) The waiting time for the rest of the instances of the process is calculated as:
a) If the time quantum is greater than the remaining burst time then waiting
time is calculated as:
a[i].wait time=count + tq
b) Else if the time quantum is greater than the remaining burst time then waiting
time is calculated as:
a[i].wait time=count - remaining burst time
4: Calculate the average waiting time and average turnaround time
5: Print the results of the step 4.

PROGRAM:

#include&lt;stdio.h&gt;
void main()
{
int b[10],i,j=1,n,temp,burst[10],wait[10],turn[10],p[10],a=1,q,tat[10],t1=0;
float t=0,w=0;
printf(&quot;Enter the no of process &amp; Q&quot;);
scanf(&quot;%d%d & quot;,&amp;n,&amp;q);
burst[0]=0;
b[0]=0;
tat[0]=0;
p[0]=0;
printf(&quot; Enter burst time & quot;);
for(i=1;i&lt;=n;i++)
scanf(&quot;%d& quot;,& amp; burst[i]);
for(i=1;i&lt;=n;i++)
b[i]=burst[i];
printf(&quot;\n\n\t\t Gantt chart\n& quot;);
printf(&quot; \n&quot;);
for(i=1;i&lt;=n;i++)
{
if(b[i]&gt;0)
{
a=1;
printf(& quot;P%d\t|& quot;, i);
if(b[i]&gt;=q)
{
t1=t1+q;
p[j]=t1;
j++;
}
else if(b[i]&lt;q)
{
t1=t1+b[i];
p[j]=t1;
j++;
}
b[i]=b[i]-q;
if(b[i]&lt;=0)
tat[i]=t1;
}
else
a++;
if(a==n+1)
break;
if(i==n)
i=0;
}
printf(&quot;\n \n&quot;);
for(i=0;i&lt;j;i++)
printf(&quot;%d\t&quot;,p[i]);
for(i=1;i&lt;=n;i++)
{
t=t+tat[i];
w=w+tat[i]-burst[i];
}
w=w/n;
t=t/n;
printf(&quot;\n The average waiting time is %0.2f&quot;,w);
printf(&quot;\n The average turn around time is %0.2f&quot;,t);
}

OUTPUT:

cc rr. c
./a. out
Enter the number of processes 3
Enter the time quantum 3
Enter the Burst Time P1 3
Enter the Burst Time P2 4
Enter the Burst Time P3 2
Gantt Chart
p1 p2 p3 p2
03689
The average Waiting Time 3.666667
The average Turnaround Time 6.6666

RESULT:
The FCFS, SJFS, Priority and Round Robin scheduling algorithms is implemented
using C and executed successfully.

Exp No.3 DEMONSTRATION OF SEMAPHORES


Date:

AIM:

To Implement Demonstration of Semaphores Using C.

PROBLEM DESCRIPTION:

CONTEXT:

Imagine a scenario where multiple threads need to access a limited number of resources,
such as a pool of database connections, printer access, or a shared buffer in producer-
consumer problems.

COMPONENTS:

1. Semaphore: An integer variable used to control access. It can be:


o Binary Semaphore: Takes values 0 or 1 (like a mutex).
o Counting Semaphore: Can take any non-negative integer value,
representing the number of available resources.
2. Threads/Processes: Multiple threads that attempt to access the shared resource.
3. Shared Resource: The limited resource that threads are trying to access (e.g., a
database connection).

PROBLEM SCENARIO:

 Shared Resource: A fixed number of database connections (e.g., 3 connections).


 Threads: Multiple threads (e.g., 10 threads) that need to perform database
operations.

ALGORITHM:

1. Initialize Semaphore: Set the semaphore count to the number of available


resources (3 in this case).
2. Thread Execution:
o Each thread attempts to acquire the semaphore before accessing the database.
o If the semaphore count is greater than 0, the thread decrements the
semaphore and proceeds.
o If the count is 0, the thread is blocked until a resource is released.
3. Resource Access:
o The thread performs its database operation.
o After completing the operation, the thread releases the semaphore,
incrementing the count, indicating a resource is now available.
4. Thread Completion:

The thread finishes and exits, allowing other blocked threads to acquire the
semaphore and access the resource.

PROGRAM:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define NUM_THREADS 5
sem_t semaphore;
void* access_shared_resource(void* thread_id) {
long tid = (long)thread_id;
// Wait (P operation)
sem_wait(&semaphore)
printf("Thread %ld: Accessing shared resource...\n", tid);
sleep(1); // Simulate resource access
printf("Thread %ld: Finished accessing shared resource.\n", tid);
// Signal (V operation)
sem_post(&semaphore);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
// Initialize semaphore with value 2 (2 resources available)
sem_init(&semaphore, 0, 2);
// Create threads
for (long i = 0; i < NUM_THREADS; i++) {
pthread_create(&threads[i], NULL, access_shared_resource, (void*)i);}
// Wait for all threads to complete
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL); }
// Destroy semaphore
sem_destroy(&semaphore);
return 0;
}
OUTPUT:

Thread 0: Accessing shared resource...


Thread 1: Accessing shared resource...
Thread 2: Finished accessing shared resource.
Thread 3: Accessing shared resource...
Thread 4: Finished accessing shared resource.
Thread 0: Finished accessing shared resource.
Thread 1: Finished accessing shared resource.
Thread 3: Finished accessing shared resource.

RESULT:

The semaphore successfully restricts the number of threads accessing the shared resource
to 2 at any given time. This prevents race conditions and ensures that access to the shared
resource is managed effective .
Exp No.4 IMPLEMENTATION OF PRODUCER-
CONSUMER PROBLEM
Date:

AIM:
To write a C program to implement the Producer & consumer Problem
(Semaphore).

PROBLEM DESCRIPTION:

1. Processes:
o Producers: These processes create data items and place them into a shared
buffer.
o Consumers: These processes take data items from the shared buffer for
processing.
2. Shared Buffer:
o A finite-size buffer (often implemented as a queue) that holds the items
produced by producers before they are consumed.
3. Constraints:
o Buffer Capacity: The buffer has a limited size. If a producer tries to add an
item when the buffer is full, it must wait.
o Empty Buffer: If a consumer tries to remove an item from an empty buffer,
it must wait until an item is available.
o Synchronization: Proper synchronization mechanisms must be in place to
prevent race conditions and ensure that producers and consumers do not
access the buffer simultaneously in a way that causes data corruption.

ALGORITHM:

1: The Semaphore mutex, full & empty are initialized.


2: In the case of producer process
a) Produce an item in to temporary variable.
b) If there is empty space in the buffer check the mutex value for enter into the
critical section.
c) If the mutex value is 0, allow the producer to add value in the temporary
variable to the buffer.
3: In the case of consumer process
a) It should wait if the buffer is empty
b) If there is any item in the buffer check for mutex value, if the
mutex==0,remove item from buffer
c) Signal the mutex value and reduce the empty value by 1.Consume the item.
4: Print the result
PROGRAM:

#include<stdio.h>
char
buf[20],p[20],cos[20];
int mutex,i,k,c,sz,n;
mutex=0;
void prosig()
{
mutex=mutex+1;
}
void consig()
{
mutex=mutex-1;
}
int buffer(int mutex)
{
if(mutex==
0) return 1;
else
return
0;
}
void producer(int sz)
{
int c;
c=buffer(mutex
); if(c==1)
{
printf("\nProducer can produce the item and give $ for
exit\n"); i=0;
while(i<sz&&(p[i]=getchar())!='$')
{
buf[i]=p[i]
; i++;
}
k=i;
prosig()
;
printf("\nProduction done successfully\n");
}
else if(k<sz)
{
printf("Producer can also produce
items"); while((p[k]=getchar())!='$')
{
buf[k]=p[k
]; k++;
}
prosig();
printf("\nProduction done successfully\n");
}
else if(k>=sz)
{
printf("\nBuffer is full,can't produce\n");
}
}
void consumer()
{
int c1;
c1=buffer(mutex
); if(c1==0)
{
printf("\nConsumer can consume
item\n"); for(i=0;i<k;i++)
cos[i]=buf[i];
printf("\nConsumed item
is:\n"); for(i=0;i<k;i++)
printf("\n%c",cos[i]);
consig();
printf("\nSuccessfully done\n");
}
else
{
printf("\nBuffer is empty,can't consume\n");
}
}
int main()
{
int op,sz;
printf("Enter the buffer
size"); scanf("%d",&sz);
do
{
printf("\n1.Producer\t2.Consumer\t3.Exit\
n"); printf("\nEnter your choice\n");
scanf("%d",&op);
switch(op)
{
case 1:
producer(sz
); break;
case 2:
consumer(
); break;
case 3:
exit(0);
}
}
while(op<=2
); return 0;
}

OUTPUT:

cc pcp. c
./a. out
Enter the buffer size5
1.Producer 2.Consumer
3.Exit Enter your
choice
1
Producer can produce the item and give $ for exit

ho$
Production done successfully
1.Producer 2.Consumer
3.Exit Enter your
choice
1
Producer can also produce items
ney$ Production done successfully
1.Producer 2.Consumer 3.Exit
Enter your choice
1
Buffer is full, can't produce
1.Producer 2.Consumer
3.Exit Enter your
choice
2
Consumer can consume
item Consumed item is:
h

n
e
y
Successfully done
1. Producer 2.Consumer
3.Exit Enter your choice
3

RESULT:
The Producer & consumer Problem using Semaphore is implemented using C and
executed.
.
Exp No.5 SIMULATION OF BANKERS ALGORITHM FOR
DEADLOCK AVOIDANCE
Date:

AIM:

Write a C program to simulate Bankers Algorithm for Deadlock Avoidance and Prevention.

PROBLEM DESCRIPTION:

In a multiprogramming environment, several processes may compete for a finite number of


resources.
A process requests resources; if the resources are not available at that time, the process enters a
waiting state. Sometimes, a waiting process is never again able to change state, because there
sources it has requested are 4held by other waiting processes. This situation is called a deadlock.
Deadlock avoidance is one of the techniques for handling deadlocks. This approach requires that
the operating system be given in advance additional information concerning which resources a
process will request and use during its life time. With this additional knowledge, it can decide for
each request whether or not the process should wait. To decide whether the current request can be
satisfied or must be delayed, the system must consider the resources currently available, the
resources currently allocated to each process, and the future requests and releases of each process.
Banker’s algorithm is a deadlock avoidance algorithm that is applicable to a system with multiple
instances of each resource type.

HARDWARE REQUIREMENTS:I

Ntel based Desktop Pc

RAM of 512 MB
SOFTWAREREQUIREMENTS:

Turbo C/Borland C.
THEORY:
DEADLOCKAVOIDANCE

To implement deadlock avoidance & Prevention by using Banker’s Algorithm.


BANKER’SALGORITHM:

When a new process enters a system, it must declare the maximum number of instances of
each resource type it needed. This number may exceed the total number of resources in the
system. When the user request a set of resources, the system must determine whether the
allocation of each resources will leave the system in safe state. If it will the resources are
allocation; otherwise the process must wait until some other process release the resources.
DATASTRUCTURES:

 n-Number of process, m-number of resource types.


 Available: Available[j]=k, k–instance of resource type Rj is available.
 Max: If max[i,j]=k, Pi may request at most k instances resource Rj.
 Allocation: If Allocation[i,j]=k, Pi allocated to k instances of resource Rj
 Need: If Need [I, j]=k, Pi may need k more instances of resource type Rj,

Need[I, j]=Max[I, j]-Allocation[I, j];

SAFETY ALGORITHM:

1. Work and Finish be the vector of length m and n respectively,


Work=Available and Finish[i] =False.
2. Find a n i such that both
 Finish[i]=False
 Need<=Work
IfnosuchIexistsgotostep4.
3. work=work+ Allocation, Finish[i]=True;
4. if Finish[1]=True for all I, then the system is in safe state.

RESOURCE REQUEST ALGORITHM:

Let Request I be request vector for the process Pi, If request i=[j]=k, then process Pi wants
k instances of resource type Rj.
1. If Request<=Need I go to step2.Otherwiseraise an error condition.
2. If Request<=Available go to step3.OtherwisePimustsincetheresourcesareavailable.
3. HavethesystempretendtohaveallocatedtherequestedresourcestoprocessPibymodifying
the state as follows;
Available=Available-Request I;
Allocation I=Allocation +Request
I; Need i=Need i-Request I;

If the resulting resource allocation state is safe, the transaction is completed and process Pi is
allocated its resources. However if the state is unsafe, the Pi must wait for Request i and the old
resource- allocation state is restored.

ALGORITHM:

1. Start the program.


2. Get the values of resources and processes.
3. Get the avail value.
4. After allocation find the need value.
5. Check whether its possible to allocate.
6. If it is possible then the system is in safe state.
7. Else system is not in safety state.
8. If the new request comes then check that the system is in safety.
9. Or not if we allow the request.
10. Stop the program
Need[I, j]=Max[I,j]-Allocation[I,j];

SAFETY ALGORITHM:

5. Work and Finish be the vector of length m and n respectively,


Work=Available and Finish[i] =False.
6. Find an I such that both
 Finish[i]=False
 Need<=Work
IfnosuchIexistsgotostep4.
7. work= work+ Allocation, Finish[i]=True;
8. if Finish[1]=True for all I, then the system is in safe state.

RESOURCE REQUEST ALGORITHM:

Let Request I be request vector for the process Pi, If request i=[j]=k, then process Pi want
sk instances of resource type Rj.
4. If Request<=NeedIgotostep2.Otherwiseraise an error condition.
5. If Request<=Available go to step3.OtherwisePimustsincetheresourcesareavailable.
6. HavethesystempretendtohaveallocatedtherequestedresourcestoprocessPibymodifying
the state as follows;
Available=Available-Request I;
Allocation I= Allocation+ Request
I; Need i=Need i-Request I;

If the resulting resource allocation state is safe, the transaction is completed and process Pi is
allocated its resources. How ever if the state is unsafe, the Pi must wait for Request i and the old
resource- allocation state is restored.

ALGORITHM:

11. Start the program.


12. Get the values of resources and processes.
13. Get the avail value.
14. After allocation find the need value.
15. Check whether its possible to allocate.
16. If it is possible then the system is ins afe state.
17. Else system is not in safety state.
18. If then request comes then check that the system is in safety.
19. or not if we allow the request.
20. Stop the program.
PROGRAM:

#include< stdio. h>struct


da {
intmax[10],al[10],need[10],before[10],after[10];
}p[10];
voidmain(){
inti,j,k,l,r,n,tot[10],av[10],cn=0,cz=0,temp=0,c=0;
printf("\n Enter the no of processes:");
scanf("%d",&n);
printf("\nEnter the no of resources:");
scanf("%d",&r);
for(i=0;i<n;i++) {
printf("process%d\n",i+1);
for(j=0;j<r;j++) {
printf("maximumvalueforresource%d:",j+1);
scanf("%d",&p[i].max[j]);
}
for(j=0;j<r;j++){
printf("allocatedfromresource%d:",j+1);
scanf("%d",&p[i].al[j]);
p[i].need[j]=p[i].max[j]-p[i].al[j];
}
}
for(i=0;i<r;i++){
printf("Enter total value of resource%d:",i+1);
scanf("%d",&to t[i]);
}
for(i=0;i<r;i++) {
for(j=0;j<n;j++)
temp=temp+p[j].al[i];
av[i]=tot[i]-temp; temp=0;
}
printf("\n\t max allocated needed to talavail");
for(i=0;i<n;i++) {
printf("\n P%d \t",i+1);
for(j=0;j<r;j++)
printf("%d",p[i].max[j]);
printf("\t"); for(j=0;j<r;j++)
printf("%d",p[i].al[j]);
printf("\t"); for(j=0;j<r;j++)
printf("%d",p[i].need[j]);
printf("\t"); for(j=0;j<r;j++)
{
if(i==0)
printf("%d",tot[j]);
}
printf("");
for(j=0;j<r;j++) {
if(i==0)
printf("%d",av[j]);
}
}
printf("\n\n\t AVAIL BEFORE\t AVAIL AFTER");
for(l=0;l<n;l++)
{
for(i=0;i<n;i++)
{
for(j=0;j<r;j++)
{
if(p[i].need[j]>av[j])
cn++; if(p[i].max[j]==0)
cz++;
}
if(cn==0&&cz!=r)
{
for(j=0;j<r;j++)
{
p[i].before[j]=av[j]-p[i].need[j];
p[i].after[j]=p[i].before[j]+p[i].max[j];
av[j]=p[i].after[j];
p[i].max[j]=0;
}
printf("\n p%d \t",i+1);
for(j=0;j<r;j++)
printf("%d",p[i].before[j]);
printf("\t");for(j=0;j<r;j++)
printf("%d",p[i].after[j]);
cn=0;
cz=0; c++;
break;
}
else { cn=0;cz=0;
}
}
}
if(c==n)
printf ("\n the above sequence is a safe sequence");
else
printf ("\n deadlock occured" );
}

OUTPUT:

//TESTCASE 1:

ENTERTHENO.OFPROCESSES:4

ENTERTHENO.OFRESOURCES:3

PROCESS 1:
MAXIMUMVALUEFORRESOURCE1:3
MAXIMUMVALUEFORRESOURCE2:2
MAXIMUMVALUEFORRESOURCE3:2
ALLOCATED FROM RESOURCE 1:1
ALLOCATED FROM RESOURCE 2:0
ALLOCATED FROM RESOURCE 3:0

PROCESS 2
MAXIMUMVALUEFORRESOURCE1:6
MAXIMUMVALUEFORRESOURCE2:1
MAXIMUMVALUEFORRESOURCE3:3
ALLOCATED FROM RESOURCE 1:5
ALLOCATED FROM RESOURCE 2:1
ALLOCATED FROM RESOURCE 3:1

PROCESS 3
MAXIMUMVALUEFORRESOURCE1:3
MAXIMUMVALUEFORRESOURCE2:1
MAXIMUMVALUEFORRESOURCE3:4
ALLOCATED FROM RESOURCE 1:2
ALLOCATED FROM RESOURCE 2:1
ALLOCATED FROM RESOURCE 3:1

PROCESS4
MAXIMUM VALUE FOR RESOURCE 1:4
MAXIMUM VALUE FOR RESOURCE 2:2
MAXIMUM VALUE FOR RESOURCE 3:2
ALLOCATED FROM RESOURCE 1:0
ALLOCATED FROM RESOURCE 2:0
ALLOCATED FROM RESOURCE 3:2
ENTERTOTALVALUEOFRESOURCE1:9
ENTERTOTALVALUEOFRESOURCE2:3

ENTERTOTALVALUEOFRESOURCE 3:6
RESOURCESALLOCATEDNEEDED TOTALAVAIL
P1 322 100 222 936 112
P2 613 511 102
P3 314 211 103
P4 422 002 420

AVAILBEFOREAVAILAFTER
P2 010 623
P1 401 723
P3 620 934
P4 514 936

THE ABOVE SEQUENCE IS A SAFE SEQUENCE

RESULT:

The simulate Bankers Algorithm for Deadlock Avoidance program was successfully.
Exp No.6 CREATION OF VIRTUAL MACHINE IN A
HYPERVISOR
Date:

AIM:

To understand the process of creating and managing virtual machines (VMs) using a
hypervisor, and to explore the benefits and functionalities of virtualization.

INTRODUCTION TO HYPERVISORS:

A hypervisor is software that creates and runs virtual machines. There are two types of
hypervisors:

 Type 1 (Bare-Metal): Runs directly on the hardware (e.g., VMware ESXi,


Microsoft Hyper-V).
 Type 2 (Hosted): Runs on top of an operating system (e.g., VMware Workstation,
Oracle Virtual Box).

ALGORITHM:

1. Select Hypervisor: Choose a hypervisor to use (e.g., Virtual Box).


2. Initialize Hypervisor: Open the hypervisor application.
3. Create a New VM:
o Specify VM name and operating system type.
o Allocate resources (CPU, RAM, disk space).
4. Configure VM Settings:
o Set network options.
o Adjust storage settings.
5. Install Operating System: Load the OS installation media (ISO file).
6. Start the VM: Boot the VM and complete the OS installation.
7. Verify Operation: Ensure the VM runs correctly and can perform tasks.

SAMPLE PROGRAM (USING VIRTUALBOX CLI):

Assuming you have Virtual Box installed, you can create a VM using the command line:

# Create a new VM
V Box Manage create vm --name "My VM" --register

# Set VM parameters
V Box Manage modify vm "My VM" --memory 2048 –cpu s 2 –os type
"Ubuntu_64"

# Create a virtual hard disk


V Box Manage create hd --filename "MyVM.vdi" --size 20000

# Configure storage settings


V Box Manage storage ctl "My VM" --name "SATA Controller" --add sata --
controller Intel Ahci
V Box Manage storage attach "My VM" –storage ctl "SATA Controller" --port 0 --device
0 --type hdd --medium "MyVM.vdi"

# Attach ISO for OS installation


V Box Manage storage attach "My VM" –storage ctl "SATA Controller" --port 1 --
device 0 --type dvd drive --medium "/path/to/ubuntu.iso"

# Start the VM
V Box Manage start vm "My VM" --type headless

Output

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

RESULT:

To understand the process of creating and managing virtual machines (VMs) using a
hypervisor, and to explore the benefits and functionalities of virtualization Was Program
Successfully.

You might also like