Operating System Lab Manual
Operating System Lab Manual
LABORATORY MANUAL
AY: 2022-2023
GNITC – SPECIAL BRANCH
YEAR II
SEMESTER II
STREAM : CSE - DS
DOCUMENT NO : GNITC–
VERIFIED BY
INDEX
SL.NO. CONTENTS
3. Lab Objective
4. Lab outcomes
Guidelines to students
6. a) Standard Operating Procedure (SOP)
b) General guidelines
PEO 1: Graduates shall have the ability to apply knowledge across the disciplines and in emerging
areas of Artificial Intelligence and Machine Learning for higher studies, research, employability,
product development and handle the realistic problems.
PEO 2: Graduates shall have good communication skills, possess ethical values, sense Responsibility
to serve the society, and protect the environment.
PEO 3: Graduates shall possess academic excellence with innovative insight, managerial skills,
leadership qualities, knowledge of contemporary issues and understand the need for lifelong learning
for a successful professional career.
1. Ability to design, develop, test and debug software applications, evaluate and recognize potential
risks and provide innovative solutions.
To become a premier Computer Science and Engineering department by imparting high quality
education, ethical values, provide creative environment for innovation and global opportunities
M1: Nurture young individuals into knowledgeable, skilful and ethical professionals in their pursuit
of Information Technology.
M2: Transform the students through soft skills, excellent teaching learning process and sustain high
performance by innovations.
M3: Extensive partnerships and collaborations with foreign universities to enrich the knowledge and
research.
M4: Develop industry-interaction for innovation and product development to provide good
placements.
GNITC – SPECIAL BRANCH
1
GNITC – SPECIAL BRANCH
etc) in their own accounts. Each student's work is safe and secure
from other students.
Rational Rose Software is installed in some systems
Using this software, students can depict UML diagrams of their
projects.
Softwares installed: C, C++, JDK1.5, MASM, OFFICE-XP, J2EE and
DOT NET, Rational Rose.
Systems are provided for students in the 1:1 ratio.
Systems are assigned with numbers and the same system is allotted
for students when they do the lab.
2
GNITC – SPECIAL BRANCH
Students are asked to carry their lab observation book and record
book.
Students must use the equipments with care, any damage caused to
the equipment by the student is punishable.
Students are not allowed to use their cell phones/pendrives/CDs.
Student need to maintain proper dress code.
Student are supposed to occupy the systems allotted to them.
Students are not allowed to make noise in the lab.
After completion of each experiment student need to update their
observation notes and same to be reflected in the record.
Lab records needs to be submitted after completion of each
experiment and get it corrected with the concerned lab faculty.
If a student is absent for any lab, he/she need to complete the
experiment in the free time before attending the next lab.
Step1: Students have to write the Date, aim, Software and Hardware
requirements for the scheduled experiment in the observation book.
Step2: Students have to listen and understand the experiment
explained by the faculty and note down the important points in the
observation book.
Step3: Students need to write procedure/algorithm in the observation
book.
Step4: Analyze and Develop/implement the logic of the program by
the student in respective platform
Step5: After approval of logic of the experiment by the faculty then
the experiment has to be executed on the system.
Step6: After successful execution, the results have to be recorded in
the observation book and shown to the lab in charge faculty..
Step7: Students need to attend the Viva-Voce on that experiment and
write the same in the observation book.
Step8: Update the completed experiment in the record and submit to
the concerned faculty in- charge.
Before staring of the first lab session students must buy the record
book and bring the same to the lab.
Regularly (Weekly) update the record after completion of the
experiment and get it corrected with concerned lab in-charge for
continuous evaluation.
3
GNITC – SPECIAL BRANCH
In case the record is lost, inform on the same day to the faculty in
charge and submit the new record within 2 days for correction.
If record is not submitted in time or record is not written properly, the
record evaluation marks (5M) will be reduced accordingly.
4
GNITC – SPECIAL BRANCH
COURSE OBJECTIVES
To provide an understanding of the design aspects of operating system concepts
through simulation
Introduce basic Unix commands, system call interface for process management,
inter process communication and I/O in Unix.
COURSE OUTCOMES
Simulate and implement operating system concepts such as scheduling,
deadlock management, file management and memory management.
Able to implement C programs using Unix system calls.
REFERENCE BOOK:
Operating Systems – Internals and Design Principles, William
Stallings,
Fifth Edition–2005, Pearson Education/PHI
Operating System - A Design Approach-Crowley, TMH.
Modern Operating Systems, Andrew S Tanenbaum, 2nd edition,
Pearson/PHI
UNIX Programming Environment, Kernighan and Pike, PHI/Pearson
Education
UNIX Internals: The New Frontiers, U. Vahalia, Pearson Education.
5
GNITC – SPECIAL BRANCH
LAB EXPERIMENTS
WEEK-1:
Simulate the following CPU scheduling algorithms
a. FCFS
b. SJF
c. RR
d. Priority
a) AIM: To Simulate the First Come First Serve Scheduling Algorithms.
Recommended Hardware/Software Requirements:
● Hardware Requirements: Intel Based desktop PC LANS Connected with minimum of 166
MHZ or faster processor with at least 64 MB RAM and 100 MB free disk space.
● Software Requirements : Linux/unix
● Prerequisite:
Theory:
First-Come, First-Serve scheduling (FCFS): In this, which process enter the ready queue first
is served first. The OS maintains DS that is ready queue. It is the simplest CPU scheduling
algorithm. If a process request the CPU then it is loaded into the ready queue, which process is
the head of the ready queue, connect the CPU to that process.
ALGORITHM:
Step-1- Input the processes along with their burst time (bt).
Step-2- Find waiting time (wt) for all processes.
Step-3- As first process that comes need not to wait so waiting time for process 1 will be
0 i.e. wt[0] = 0.
Step-4- Find waiting time for all other processes i.e. for process i ->
wt[i+1] = bt[i] + wt[i] .
Step-5- Find turnaround time tt[i+1]=tt[i]+bt[i+1]
Step-6- Find average waiting time = total_waiting_time / no_of_processes.
Step-7- Similarly, find average turnaround time = total_turn_around_time / No_of_processes.
PROGRAM:
#include<stdio.h>
#include<conio.h>
6
GNITC – SPECIAL BRANCH
void main()
{
int i,j,bt[10],n,wt[10],tt[10],w1=0,t1=0;
float aw,at;
clrscr();
printf("enter no. of processes:\n");
scanf("%d",&n);
printf("enter the burst time of processes:");
for(i=0;i<n;i++)
scanf("%d",&bt[i]);
for(i=0;i<n;i++)
{
wt[0]=0;
tt[0]=bt[0];
wt[i+1]=bt[i]+wt[i];
tt[i+1]=tt[i]+bt[i+1];
w1=w1+wt[i];
t1=t1+tt[i];
}
aw=w1/n;
at=t1/n;
printf("\nbt\t wt\t tt\n");
for(i=0;i<n;i++)
printf("%d\t %d\t %d\n",bt[i],wt[i],tt[i]);
printf("aw=%f\n,at=%f\n",aw,at); getch();
}
7
GNITC – SPECIAL BRANCH
VIVA QUESTIONS
1. What is First-Come-First-Served (FCFS) Scheduling?
2. Why CPU scheduling is required?
3. Which technique was introduced because a single job could not keep both the CPU and the I/O
devices busy?
a) Time-sharing b) Spooling c) Preemptive scheduling d) Multiprogramming
4. CPU performance is measured through .
a) Throughput b) MHz c) Flaps d) None of the above
5. Which of the following is a criterion to evaluate a scheduling algorithm?
a) CPU Utilization: Keep CPU utilization as high as possible.
b) Throughput: number of processes completed per unit time.
c) Waiting Time: Amount of time spent ready to run but not running.
d) All of the above
8
GNITC – SPECIAL BRANCH
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main()
{
int i,j,bt[10],t,n,wt[10],tt[10],w1=0,t1=0;
float aw,at;
clrscr();
9
GNITC – SPECIAL BRANCH
t=bt[i];
bt[i]=bt[j];
bt[j]=t;
}
}
for(i=0;i<n;i++)
printf("%d",bt[i]);
for(i=0;i<n;i++)
{
wt[0]=0;
tt[0]=bt[0];
wt[i+1]=bt[i]+wt[i];
tt[i+1]=tt[i]+bt[i+1];
w1=w1+wt[i];
t1=t1+tt[i];
}
aw=w1/n;
10
GNITC – SPECIAL BRANCH
at=t1/n;
printf("\nbt\t wt\t tt\n");
for(i=0;i<n;i++)
printf("%d\t %d\t %d\n",bt[i],wt[i],tt[i]);
printf("aw=%f\n,at=%f\n",aw,at); getch();
}
VIVA QUESTIONS:
1) The optimum CPU scheduling algorithm is
a) FIFO b) SJF with preemption c)SJF without preemption d)Round Robin.
2) In terms of average wait time the optimum scheduling algorithm is
a) FCFS b)SJF c)Priority d)RR
11
GNITC – SPECIAL BRANCH
If the process may have a CPU burst of less than one time slice then the process release
the CPU voluntarily. The scheduler will then process to next process ready queue otherwise; the
process will be put at the tail of the ready queue.
ALGORITHM:
1. The queue structure in ready queue is of First In First Out (FIFO) type.
2. A fixed time is allotted to every process that arrives in the queue. This fixed time is known as
time slice or time quantum.
3. The first process that arrives is selected and sent to the processor for execution. If it is not able
to complete its execution within the time quantum provided, then an interrupt is generated using
an automated timer.
4. The process is then stopped and is sent back at the end of the queue. However, the state is
saved and context is thereby stored in memory. This helps the process to resume from the point
where it was interrupted.
5. The scheduler selects another process from the ready queue and dispatches it to the processor
for its execution. It is executed until the time Quantum does not exceed.
6. The same steps are repeated until all the process are finished.
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main()
{
12
GNITC – SPECIAL BRANCH
int st[10],bt[10],wt[10],tat[10],n,tq;
int i,count=0,swt=0,stat=0,temp,sq=0;
float awt=0.0,atat=0.0;
clrscr();
printf("Enter number of processes:");
scanf("%d",&n);
printf("Enter burst time for sequences:");
for(i=0;i<n;i++)
{
scanf("%d",&bt[i]);
st[i]=bt[i];
}
printf("Enter time quantum:");
scanf("%d",&tq);
while(1)
{
for(i=0,count=0;i<n;i++)
{
temp=tq;
if(st[i]==0)
{
count++;
continue;
}
if(st[i]>tq)
st[i]=st[i]-tq;
else
13
GNITC – SPECIAL BRANCH
if(st[i]>=0)
{
temp=st[i];
st[i]=0;
}
sq=sq+temp;
tat[i]=sq;
}
if(n==count)
break;
}
for(i=0;i<n;i++)
{
wt[i]=tat[i]-bt[i];
swt=swt+wt[i];
stat=stat+tat[i];
}
awt=(float)swt/n; 11
atat=(float)stat/n;
printf("Process_no Burst time Wait time Turn around time");
for(i=0;i<n;i++)
printf("\n%d\t %d\t %d\t %d",i+1,bt[i],wt[i],tat[i]);
printf("\nAvg wait time is %f Avg turn around time is %f",awt,atat);
getch();
}
14
GNITC – SPECIAL BRANCH
VIVA QUESTIONS:
1. Round Robin scheduling is used in
a) Disk scheduling b)CPU scheduling
c)I/O scheduling d)Multitasking
2. What are the dis-advantages of RR Scheduling Algorithm?
3. What are the advantages of RR Scheduling Algorithm?
4. Super computers typically employ .
a) Real time Operating system b) Multiprocessors OS
c) desktop OS d) None of the above
5. An optimal scheduling algorithm in terms of minimizing the average waiting time of a given
set of processes is .
a) FCFS scheduling algorithm b)Round robin scheduling algorithm
15
GNITC – SPECIAL BRANCH
ALGORITHM:
1. Start the process
2. Declare the array size
3. Get the number of elements to be inserted
4. Select the process which have highest priority will execute first
5. If two process have same burst length then FCFS scheduling algorithm used
6. Make the average waiting the length of next process
7. Start with the first process from it’s selection as above and let other process to be in
queue
8. Calculate the total number of burst time
9. Display the values
10. Stop the process
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main()
{
int i,j,pno[10],prior[10],bt[10],n,wt[10],tt[10],w1=0,t1=0,s;
16
GNITC – SPECIAL BRANCH
float aw,at;
clrscr();
printf("enter the number of processes:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("The process %d:\n",i+1);
printf("Enter the burst time of processes:");
scanf("%d",&bt[i]);
printf("Enter the priority of processes %d:",i+1);
scanf("%d",&prior[i]);
pno[i]=i+1;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(prior[i]<prior[j])
{
s=prior[i];
prior[i]=prior[j];
prior[j]=s;
s=bt[i];
bt[i]=bt[j];
bt[j]=s;
s=pno[i];
pno[i]=pno[j];
17
GNITC – SPECIAL BRANCH
pno[j]=s;
}
}
}
for(i=0;i<n;i++)
{
wt[0]=0;
tt[0]=bt[0];
wt[i+1]=bt[i]+wt[i];
tt[i+1]=tt[i]+bt[i+1];
w1=w1+wt[i];
t1=t1+tt[i];
aw=w1/n;
at=t1/n;
for(i=0;i<n;i++)
printf("%d \t %d \t %d\t %d\t %d\n",pno[i],bt[i],wt[i],tt[i],prior[i]);
printf("aw=%f \t at=%f \n",aw,at);
getch();
}
18
GNITC – SPECIAL BRANCH
VIVA QUESTIONS:
19
GNITC – SPECIAL BRANCH
WEEK-2:
Write programs using the I/O system calls of UNIX/LINUX operating system (open, read, write,
close,fcntl, seek, stat, opendir, readdir)
AIM: To Write programs using the I/O system calls of UNIX/LINUX operating system (open,
read, write, close,fcntl, seek, stat, opendir, readdir)
system requirements:
● Unix/Linux distributions
● if working on windows shall have “Windows Subsystem for Linux” (WSL) / a virtual machine
with a linux distribution installed in it
Theory
System call : a fundamental interface in computer programming that allows applications or user-level
processes to request services or operations from the operating system kernel. These services can include
various low-level operations that are essential for managing hardware resources, file systems, memory,
and more. System calls provide a way for user-level programs to interact with the underlying operating
system in a controlled and secure manner.
20
GNITC – SPECIAL BRANCH
21
GNITC – SPECIAL BRANCH
program :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{ int fd, n;
char buffer[100];
// Open a file for writing
fd = open("example.txt", O_WRONLY | O_CREAT, 0666);
if (fd == -1) {
perror("open");
exit(1);
}
// Write to the file
22
GNITC – SPECIAL BRANCH
23
GNITC – SPECIAL BRANCH
output: a new files exapmle.txt will be created with “Hello, world!” in it and the contents will be
displayed to console output
2.2 : lseek
Aim: to perform lseek system call
Algorithm:
1. declare a variable fd
2. Open a desired file for reading and writing using the open function with the O_RDWR flag.
3. Check if the file descriptor returned by open is valid. If not, print an error message
using perror and exit the program
4. Use the lseek function to move the file pointer to a specific position in the file.
5. Perform a write operation at the new position using the write function.
6. Close the file using the close function
7. Exit the program with a status of 0
program :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{ int fd;
// Open a file for reading and writing
fd = open("example.txt", O_RDWR);
if (fd == -1) {
24
GNITC – SPECIAL BRANCH
perror("open");
exit(1);
}
// Seek to a specific position (e.g., 7 bytes from the beginning)
lseek(fd, 7, SEEK_SET);
// Perform read or write operations at the new position
write(fd, "welcome to os lab", 17);
close(fd);
return 0;
}
output:
prexesting file example.txt got edited
2.3 : stat
Aim: to perform stat system call
Algorithm:
1. Declare a character array filename and a struct stat variable file_stat.
2. Prompt the user to enter a filename using printf.
3. Read the filename from the user using fgets.
4. Remove the newline character from the filename using strlen and if statement.
5. Use the stat function to retrieve file information and store it in file_stat.
6. Print the file information using printf and the fields of file_stat.
25
GNITC – SPECIAL BRANCH
Program:
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main() {
char filename[256]; // You can adjust the buffer size as needed
struct stat file_stat;
printf("Enter the filename: ");
if (fgets(filename, sizeof(filename), stdin) == NULL)
{ perror("fgets");
exit(EXIT_FAILURE);
}
// Remove the newline character from the filename
size_t length = strlen(filename);
if (length > 0 && filename[length - 1] == '\n')
{ filename[length - 1] = '\0';
}
// Use the stat system call to retrieve file information
if (stat(filename, &file_stat) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
printf("File Information for %s:\n", filename);
printf("File size: %lld bytes\n", (long long)file_stat.st_size);
printf("File inode: %lu\n", (unsigned long)file_stat.st_ino);
printf("File permissions: %o\n", file_stat.st_mode & 0777);
printf("Number of hard links: %lu\n", (unsigned long)file_stat.st_nlink);
26
GNITC – SPECIAL BRANCH
Output:
2.4: fcntl
Algorithm:
27
GNITC – SPECIAL BRANCH
4. Remove the newline character from the filename using strlen and if statement.
5. Open the file for reading using the open function with the O_RDONLY flag and the filename
entered by the user.
6. Check if the file descriptor returned by open is valid. If not, print an error message
using perror and exit the program with a status of 1.
7. Use the fcntl function with the F_GETFL flag to get the current file status flags and store them
in flags.
8. Check if the return value of fcntl is -1. If so, print an error message using perror and exit the
program with a status of 1.
9. Set the O_NONBLOCK flag in flags to make the file descriptor non-blocking.
10. Use the fcntl function with the F_SETFL flag to set the new file status flags.
11. Check if the return value of fcntl is -1. If so, print an error message using perror and exit the
program with a status of 1.
12. Perform non-blocking I/O operations using the file descriptor fd.
13. Close the file descriptor using the close function.
14. Exit the program with a status of 0.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main() {
int fd; // File descriptor
int flags;
// Open a file (replace 'yourfile.txt' with the file you want to open)
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
28
GNITC – SPECIAL BRANCH
}
// Your code here, you can now use 'fd' for non-blocking I/O
// Close the file descriptor when done
close(fd);
return 0;
}
output:
note: the flags octal equivalents may not be same for everyone, these depend on system, and may differ
based on the kind of system you are using
29
GNITC – SPECIAL BRANCH
Algorithm:
1. Declare a DIR pointer dir and a struct dirent pointer entry.
2. Open a directory for reading using the opendir function and store the directory stream in dir.
3. Check if the directory stream returned by opendir is valid. If not, print an error message
using perror and exit the program with a status of 1.
4. Use a while loop to read each directory entry using the readdir function and store it in entry.
5. Check if entry is NULL. If it is, exit the loop.
6. Print the name of the directory entry using printf and the d_name field of entry.
7. Close the directory stream using the closedir function.
8. Exit the program with a status of 0.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int main() {
DIR *dir;
struct dirent *entry;
// Open a directory for reading
dir = opendir(".");
if (dir == NULL)
{ perror("opendir");
exit(1);
}
// Read and print directory entries
while ((entry = readdir(dir)) != NULL)
{ printf("%s\n", entry->d_name);
30
GNITC – SPECIAL BRANCH
}
// Close the directory
closedir(dir);
return 0;
}
output:
displays all the files/ folders in the directly this file is located in
VIVA QUESTIONS:
1. What is a system call?
2. Why are system calls important?
3. Explain the difference between a system call and a library function in UNIX
4. Explain how the open system call is used to access files in UNIX. What are the file access modes and
flags that can be specified?
5. What is the role of the read and write system calls in UNIX file I/O? How are they different from
standard input and output functions?
31
GNITC – SPECIAL BRANCH
WEEK-3:
Write a C program to simulate Bankers Algorithm for Deadlock Avoidance and Prevention
3.1 AIM: To Simulate BANKER’S ALGORITHM For Deadlock Avoidance.
Recommended Hardware/Software Requirements:
● Hardware Requirements: Intel based desktop PC LANS Connected with minimum of 166 MHZ or
faster processor with at least 64 MB RAM and 100 MB free disk space.
● Software Requirements: Turbo C
Theory:
Banker’s Algorithm:
When a new process enters a system, it must declare the maximum number of instances of each
resource type it needs. This number may exceed the total number of resources in the system. When the
user requests a set of resources, the system must determine whether the allocation of each resource will
leave the system in safe state. If it will, the resources are allocated; otherwise the process must wait until
some other process releases the resources.
Data structures:
● 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 an i such that both
o Finish[i] =False
o Need<=Work
If no such I exists go to step 4.
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 a request vector for the process Pi, If request i=[j]=k, then process Pi wants k instances
of resource type Rj.
32
GNITC – SPECIAL BRANCH
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 it's possible to allocate.
6. If it is possible then the system is in safe state.
7. Else system is not in a safe 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.
PROGRAM:
#include<stdio.h>
#include<conio.h>
struct da
{
int max[10],al[10],need[10],before[10],after[10];
}p[10];
33
GNITC – SPECIAL BRANCH
void main()
{
int i,j,k,l,r,n,tot[10],av[10],cn=0,cz=0,temp=0,c=0;
clrscr();
printf("\n Enter the no of processes:");
scanf("%d",&n);
printf("\n Enter 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("maximum value for resource %d:",j+1);
scanf("%d",&p[i].max[j]);
}
for(j=0;j<r;j++)
{
printf("allocated from resource %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",&tot[i]);
}
for(i=0;i<r;i++)
34
GNITC – SPECIAL BRANCH
{
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 total avail");
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]);
}
35
GNITC – SPECIAL BRANCH
}
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;
36
GNITC – SPECIAL BRANCH
c++;
break;
}
else
{
cn=0;
cz=0;
}
}
}
if(c==n)
printf("\n the above sequence is a safe sequence");
else
printf("\n deadlock occured");
getch();
}
OUTPUT:
37
GNITC – SPECIAL BRANCH
VIVA QUESTIONS:
38
GNITC – SPECIAL BRANCH
PROGRAM:
#include<stdio.h>
int max[10][10],alloc[10][10],need[10][10],avail[10],i,j,p,r,finish[10]={0},flag=0;
main( )
{
printf("\n\nSIMULATION OF DEADLOCK PREVENTION");
printf("Enter no. of processes, resources");
scanf("%d%d",&p,&r);printf("Enter allocation matrix");
for(i=0;i<p;i++)
for(j=0;j<r;j++)
scanf("%d",&alloc[i][j]);
printf("enter max matrix");
for(i=0;i<p;i++) /*reading the maximum matrix and availale matrix*/
for(j=0;j<r;j++)
scanf("%d",&max[i][j]);
printf("enter available matrix");
for(i=0;i<r;i++)
scanf("%d",&avail[i]);
for(i=0;i<p;i++) for(j=0;j<r;j++)
need[i][j]=max[i][j]-alloc[i][j];
fun(); /*calling function*/
if(flag==0)
{
if(finish[i]!=1)
{
printf("\n\n Failing :Mutual exclusion");
for(j=0;j<r;j++)
{ /*checking for mutual exclusion*/
39
GNITC – SPECIAL BRANCH
if(avail[j]<need[i][j])
avail[j]=need[i][j];
}
fun();
printf("\n By allocating required resources to process %d dead lock is prevented ",i);
printf("\n\n lack of preemption");
for(j=0;j<r;j++)
{
if(avail[j]<need[i][j])
avail[j]=need[i][j];
alloc[i][j]=0;
}
fun( );
printf("\n\n deadlock is prevented by allocating needed resources");
printf(" \n \n failing:Hold and Wait condition ");
for(j=0;j<r;j++)
{ /*checking hold and wait condition*/
if(avail[j]<need[i][j])
avail[j]=need[i][j];
}
fun( );
printf("\n AVOIDING ANY ONE OF THE CONDITION, U CAN PREVENT DEADLOCK");
}
}
}
fun()
{
while(1)
{
40
GNITC – SPECIAL BRANCH
for(flag=0,i=0;i<p;i++)
{
if(finish[i]==0)
{
for(j=0;j<r;j++)
{
if(need[i][j]<=avail[j])
continue;
else
break;
}
if(j==r)
{
for(j=0;j<r;j++)
avail[j]+=alloc[i][j];
flag=1;
finish[i]=1;
}
}
}
if(flag==0)
break;
}
}
41
GNITC – SPECIAL BRANCH
OUTPUT:
SIMULATION OF DEADLOCK PREVENTION
VIVA QUESTIONS:
1. When will the Banker’s algorithm be used?
2. What is the situation in which a process is waiting on another process, which is also waiting on
another process ... which is waiting on the first process. None of the processes involved in this circular
wait are making progress.
3. What is a safe state?
4. What are the conditions that cause deadlock?
5. How do we calculate the need for a process?
42
GNITC – SPECIAL BRANCH
WEEK-4:
Write a C program to implement the Producer – Consumer problem using semaphores
usingUNIX/LINUX system calls.
3.1 AIM: To Write a C program to implement the Producer – Consumer problem using semaphores
usingUNIX/LINUX system calls system requirements:
● Unix/Linux distributions
● if working on windows shall have “Windows Subsystem for Linux” (WSL) / a virtual machine
with a linux distribution installed in it
Theory:
Threads: Threads are also known as lightweight processes. They share the same memory space and
resources within a process, enabling them to run concurrently.
Producer thread: the thread which writes information to the memory consumer thread: the thread which
reads information from the memory cases in producer – consumer problem :
● case 1 : production speed is equal to consumption speed
◦ no synchronization problem
● case 2 : production speed is greater than consumption speed
◦ synchronization problem
◦ the buffer will be full and data is lost
● case 3 : production speed is lesser than consumption speed
◦ synchronization problem
◦ the buffer will be empty and consumer needs to wait for producer
Semaphores: Semaphores are a synchronization primitive used in computer science and concurrent
programming to control access to shared resources in a multi-threaded or multi-process environment
Types of semaphores:
● binary semaphore:
◦ A binary semaphore is also known as a mutex (short for "mutual exclusion").
◦ It can have only two values: 0 and 1.
● counting semaphores:
◦ A counting semaphore can have a non-negative integer value.
◦ Counting semaphores are more versatile and can be used for a variety of synchronization
tasks.
Operation on semaphores:
● Wait operation (sem_wait) : This operation decrements the semaphore's value. If the value is
already 0, it may block the calling thread or process until the semaphore becomes greater than 0.
● Signal operation (sem_post) : This operation increments the semaphore's value. If there are
other threads or processes waiting (blocked) on the semaphore, it may unblock one of them.
43
GNITC – SPECIAL BRANCH
Algorithm:
Declare variables buffer, mutex, empty, and full.
d. Add i to the buffer and print a message indicating that i has been produced.
g. Increment i.
h. Update the index in to point to the next available slot in the buffer.
1. Declare a variable i.
2. While true, do the following:
a. If the buffer is empty, print a message indicating that the consumer is waiting.
d. Get the next item from the buffer and print a message indicating that i has been
consumed.
g. Update the index out to point to the next available slot in the buffer.
i. If the production_active flag is false and the buffer is empty, return from the thread.
program:
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define BUFFER_SIZE 4
#define MAX_ITEMS 30
int buffer[BUFFER_SIZE];
sem_t mutex, empty, full;
int in = 0, out = 0;
int production_active = 1;
int isBufferFull();
int isBufferEmpty();
void* producer(void* arg)
{ int i = 1;
while (i <= MAX_ITEMS)
{ if (isBufferFull()) {
printf("Buffer is full, producer is waiting.\n");
45
GNITC – SPECIAL BRANCH
}
sem_wait(&empty);
sem_wait(&mutex);
// add item to buffer buffer[in]
= i; printf("Produced %d\n",
i++); sem_post(&mutex);
sem_post(&full);
in = (in + 1) % BUFFER_SIZE;
46
GNITC – SPECIAL BRANCH
sem_post(&mutex);
sem_post(&empty);
// consume item
out = (out + 1) % BUFFER_SIZE;
// Introduce a random delay before consuming the next item
int delay = rand() % 1000000; // Random delay in microseconds
usleep(delay); // Sleep for the specified time
}
}
int isBufferFull()
{ int value;
sem_getvalue(&full, &value);
return value == BUFFER_SIZE;
}
int isBufferEmpty()
{ int value;
sem_getvalue(&empty, &value);
return value == BUFFER_SIZE;
}
int main() {
pthread_t producer_thread, consumer_thread;
sem_init(&mutex, 0, 1);
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
// Seed the random number generator with the current time
srand(time(NULL));
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
pthread_join(producer_thread, NULL);
47
GNITC – SPECIAL BRANCH
pthread_join(consumer_thread, NULL);
sem_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
return 0;
}
output:
Note: the output is randomly generated hence it is not same for everyone
VIVA QUESTIONS:
1. Explain the Bounded Buffer Problem
2. What Are Semaphores
3. What Are the Types Of Semaphores
4. Explain the Operations That Can Be Performed On Semaphores
5. What are threads?
48
GNITC – SPECIAL BRANCH
WEEK-5:
Write C programs to illustrate the following IPC mechanisms a) Pipes b) FIFOs c) Message Queues d)
Shared Memory system requirements:
● Unix/Linux distributions
● if working on windows shall have “Windows Subsystem for Linux” (WSL) / a virtual machine
with a linux distribution installed in it
5.1 pipes
Aim: write a c program to illustrate the IPC mechanism pipes
Algorithm:
1. Declare variables pipefd and buffer.
2. Create a pipe using the pipe function and store the file descriptors in pipefd.
3. Check if the pipe was created successfully. If not, print an error message using perror and exit
the program with a status of 1.
4. Fork a new process using the fork function and store the process ID in pid.
5. Check if the fork was successful. If not, print an error message using perror and exit the program
with a status of 1.
6. If pid is 0, do the following (child process): a. Close the write end of the pipe using close. b.
Read data from the read end of the pipe using read and store it in buff
7. er. c. Print the received data using printf. d. Close the read end of the pipe using close.
8. If pid is not 0, do the following (parent process): a. Close the read end of the pipe using close. b.
Prompt the user to enter a message using printf. c. Read the message from the user using fgets
and store it in buffer .d. Write the message to the write end of the pipe using write. e. Close the
write end of the pipe using close.
9. Exit the program with a status of 0.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
int pipefd[2];
char buffer[100];
if (pipe(pipefd) == -1)
{ perror("pipe");
exit(EXIT_FAILURE);
49
GNITC – SPECIAL BRANCH
}
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
close(pipefd[1]); // Close write end in child process
read(pipefd[0], buffer, sizeof(buffer));
printf("Child received: %s\n", buffer);
close(pipefd[0]);
} else {
close(pipefd[0]); // Close read end in parent process
printf("Enter a message: ");
fgets(buffer, sizeof(buffer), stdin);
write(pipefd[1], buffer, sizeof(buffer));
close(pipefd[1]);
}
return 0;
}
Output:
50
GNITC – SPECIAL BRANCH
5.2 FIFOs
Algorithm:
1. Create a named pipe using the mkfifo function and the permissions 0666.
2. Declare a variable buffer to hold the message to be sent or received.
3. Fork a new process using the fork function and store the process ID in pid.
4. Check if the fork was successful. If not, print an error message using perror and exit the program
with a status of 1.
5. If pid is 0, do the following (child process):
6. a. Open the named pipe for reading using the open function with the FIFO name and the
O_RDONLY flag, and store the file descriptor in fd.
b. Read data from the file descriptor using read and store it in buffer.
c. Print the received data using printf.
d. Close the file descriptor using close.
7. If pid is not 0, do the following (parent process):
8. a. Open the named pipe for writing using the open function with the FIFO name and the
O_WRONLY flag, and store the file descriptor in fd.
b. Prompt the user to enter a message using printf.
c. Read the message from the user using fgets and store it in buffer.
d. Write the message to the file descriptor using write.
e. Close the file descriptor using close.
9. Exit the program with a status of 0.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{ mkfifo("myfifo", 0666);
char buffer[100];
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
51
GNITC – SPECIAL BRANCH
}
if (pid == 0) {
int fd = open("myfifo", O_RDONLY);
read(fd, buffer, sizeof(buffer));
printf("Child received: %s\n", buffer);
close(fd);
} else {
int fd = open("myfifo", O_WRONLY);
printf("Enter a message: ");
fgets(buffer, sizeof(buffer), stdin);
write(fd, buffer, sizeof(buffer));
close(fd);
}
return 0;
}
Output:
52
GNITC – SPECIAL BRANCH
Aim: write a c program to implement the inter process communication mechanism, message
queues
Algorithm:
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msg_buffer
{ long msg_type;
char msg_text[100];
};
int main()
{ key_t key;
int msgid;
53
GNITC – SPECIAL BRANCH
Output:
54
GNITC – SPECIAL BRANCH
Algorithm
Program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <semaphore.h>
#include <fcntl.h>
int main() {
key_t key = ftok("/tmp", 65);
int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
char* shmem = (char*)shmat(shmid, (void*)0, 0);
sem_t *parent, *child;
parent = sem_open("/parent", O_CREAT, 0666, 0);
child = sem_open("/child", O_CREAT, 0666, 0);
pid_t pid = fork();
55
GNITC – SPECIAL BRANCH
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// Child process
sem_wait(parent); // Wait for the parent to signal
printf("Child received: %s\n", shmem);
shmdt(shmem);
sem_post(child); // Signal the parent that child has finished
exit(0);
} else {
// Parent process
printf("Enter a message: ");
fgets(shmem, 1024, stdin);
output:
56
GNITC – SPECIAL BRANCH
VIVA QUESTIONS:
1. What is the purpose of the fork system call
2. Explain the types of IPC mechanisms
3. How is a FIFO different from a pipe
4. What is the need of IPC
5. What is a semaphore, and how is it used for process synchronization in IPC?
57
GNITC – SPECIAL BRANCH
WEEK-6:
i. Paging
ii. Segmentation
Recommended Hardware/Software Requirements:
● Hardware Requirements: Intel based desktop PC LANS Connected with minimum of 166 MHZ or
faster processor with at least 64 MB RAM and 100 MB free disk space.
● Software Requirements : Turbo C
Prerequisite:
Theory:
PAGING: Logical address space of a process can be noncontiguous; process is allocated physical
memory whenever the latter is available Divide physical memory into fixed-sized blocks called frames
(size is power of 2, between 512 bytes and 8,192 bytes). Divide logical memory into blocks of same size
called pages , keep track of all free frames .To run a program of size n pages, need to find n free frames
and load program.
ALGORITHM:
1. Start
2. Read the number of pages
3. Read the page size
4. Allocate the memory to the pages dynamically in non contiguous locations.
5. Display the pages and their addresses.
6. Stop
PROGRAM:
#include<stdio.h>
main()
{
int i,j,arr[100],pt[20],val,pgno,offset,phymem,fs,nf;
printf("\n Memory Management paging\n");
printf("enter the size of physical memory");
scanf("%d",&phymem);
58
GNITC – SPECIAL BRANCH
for(i=20,j=0;i<phymem+20,j<phymem;i++,j++)
arr[i]=j;
printf("\n Enter size of frame or page");
scanf("%d",&fs);
nf=phymem/fs;
printf("No of frame available are\t%d",nf);
printf("\n Enter the page table");
for(i=0;i<nf;i++)
{
scanf("%d",&pt[i]);
}
printf("\n Enter the page no");
scanf("%d",&pgno);
printf("\n Enter the offset");
scanf("%d",&offset);
val=(fs*pt[pgno])+offset;
printf("the physical address is:%d\n",arr[val]);
}
OUTPUT:
59
GNITC – SPECIAL BRANCH
VIVA QUESTIONS:
1. What is the mechanism that bring a page into memory only when it is needed is called
2. What are the advantages and dis-advantages of paging?
3. Define external fragmentation? \
4. Which space of a process can be noncontiguous?
5. What is a page table?
PROGRAM:
#include<stdio.h>
#include<conio.h>
struct list
{
int seg;
int base;
int limit;
struct list *next;
} *p;
void insert(struct list *q,int base,int limit,int seg)
{
if(p==NULL)
{
60
GNITC – SPECIAL BRANCH
p=malloc(sizeof(Struct list));
p->limit=limit;
p->base=base;
p->seg=seg;
p->next=NULL;
}
else
{
while(q->next!=NULL)
{
q=q->next;
printf(“yes”)
}
q->next=malloc(sizeof(Struct list));
q->next ->limit=limit;
q->next ->base=base;
q->next ->seg=seg;
q->next ->next=NULL;
}
}
int find(struct list *q,int seg)
{
while(q->seg!=seg)
{
q=q->next;
}
return q->limit;
}
int search(struct list *q,int seg)
{
while(q->seg!=seg)
{
q=q->next;
}
return q->base;
}
main()
{
p=NULL;
int seg,offset,limit,base,c,s,physical;
printf(“Enter segment table/n”);
printf(“Enter -1 as segment value for termination\n”);
do
{
printf(“Enter segment number”);
scanf(“%d”,&seg);
if(seg!=-1)
{
61
GNITC – SPECIAL BRANCH
OUTPUT:
62
GNITC – SPECIAL BRANCH
VIVA QUESTIONS:
1. What is Segmentation?
2. What are the advantages and disadvantages of Segmentation?
3. Define external fragmentation? \
4. Which space of a process can be noncontiguous?
5. What is a page table?
63
GNITC – SPECIAL BRANCH
ALGORITHM
Step 1. Start to traverse the pages.
Step 2. If the memory holds fewer pages, then the capacity goes to step 5.
Step 3. Push pages in the queue one at a time until the queue reaches its maximum capacity or all page
requests are fulfilled.
Step 5. Else, pop the topmost page from the queue as it was inserted first.
Step 6. Replace the topmost page with the current page from the string.
Step 8. Stop
PROGRAM:
#include<stdio.h>
#include<conio.h>
int i,j,nof,nor,flag=0,ref[50],frm[50],pf=0,victim=-1;
void main()
64
GNITC – SPECIAL BRANCH
{
clrscr();
printf("\n \t\t\t FIFI PAGE REPLACEMENT ALGORITHM");
printf("\n Enter no.of frames....");
scanf("%d",&nof);
printf("Enter number of Pages.\n");
scanf("%d",&nor);
printf("\n Enter the Page No. ");
for(i=0;i<nor;i++)
scanf("%d",&ref[i]);
printf("\nThe given Pages are:");
for(i=0;i<nor;i++)
printf("%4d",ref[i]);
for(i=1;i<=nof;i++)
frm[i]=-1;
printf("\n");
for(i=0;i<nor;i++)
{
flag=0;
printf("\n\t page no %d->\t",ref[i]);
for(j=0;j<nof;j++)
{
if(frm[j]==ref[i])
{
flag=1;
break;
}
}
if(flag==0)
65
GNITC – SPECIAL BRANCH
{
pf++;
victim++;
victim=victim%nof;
frm[victim]=ref[i];
for(j=0;j<nof;j++)
printf("%4d",frm[j]);
}
}
VIVA QUESTIONS:
1. Define FIFO?
2. Which of the following statements is not true?
a) Multiprogramming implies multitasking
b) Multi-user does not imply multiprocessing
c) Multitasking does not imply multiprocessing
d) Multithreading implies multi-user
3. Define page?
4. Define Frame?
5. Write advantages and dis-advantages of FIFO?
66
GNITC – SPECIAL BRANCH
ALGORITHM:
1. Start the process
2. Declare the size
3. Get the number of pages to be inserted
4. Get the value
5. Declare counter and stack
6. Select the least recently used page by counter value
7. Stack them according to the selection.
8. Display the values
9. Stop the process
PROGRAM:
#include<stdio.h>
#include<conio.h>
main()
{
int i, j , k, min, rs[25], m[10], count[10], flag[25], n, f, pf=0, next=1;
clrscr();
printf("Enter the length of reference string -- ");
67
GNITC – SPECIAL BRANCH
scanf("%d",&n);
printf("Enter the reference string -- ");
for(i=0;i<n;i++)
{
scanf("%d",&rs[i]);
flag[i]=0;
}
printf("Enter the number of frames -- ");
scanf("%d",&f);
for(i=0;i<f;i++)
{
count[i]=0;
m[i]=-1;
}
printf("\nThe Page Replacement process is -- \n");
for(i=0;i<n;i++)
{
for(j=0;j<f;j++)
{
if(m[j]==rs[i])
{
flag[i]=1;
38
count[j]=next;
next++;
}
}
if(flag[i]==0)
{
if(i<f)
68
GNITC – SPECIAL BRANCH
{
m[i]=rs[i];
count[i]=next;
next++;
}
else
{
min=0;
for(j=1;j<f;j++)
if(count[min] > count[j])
min=j;
m[min]=rs[i];
count[min]=next;
next++;
}
pf++;
}
for(j=0;j<f;j++)
printf("%d\t", m[j]);
if(flag[i]==0)
printf("PF No. -- %d" , pf);
printf("\n");
}
printf("\nThe number of page faults using LRU are %d",pf);
getch();
}
69
GNITC – SPECIAL BRANCH
OUTPUT
VIVA QUESTIONS:
1. In which of the following page replacement policies, Bolady’s anomaly occurs?
(A)FIFO (B) LRU (C)LFU (D)SRU
2. Explain the difference between FIFO and LRU?
3. The operating system manages .
1 Memory 2 Processor 3 Disk and I/O devices 4 All of the above.
4. A program at the time of executing is called .
1 Dynamic program 2 Static program 3 Binded Program 4 A Process
5. The principle of locality of reference justifies the use of .
1 Virtual Memory 2 Interrupts 3 Main memory 4 Cache memory
70
GNITC – SPECIAL BRANCH
Optimal page replacement algorithm says that if page fault occurs then that page should be removed that
will not be used for maximum time in future.
It is also known as clairvoyant replacement algorithm or Belady’s optimal page replacement policy.
ALGORITHM:
1. Start
2. Read the number of frames
3. Read the number of pages
4. Read the page numbers
5. Initialize the values in frames to -1
6. Allocate the pages into frames by selecting the page that will not be used for the longest
period of time.
7. Display the number of page faults.
8. Stop
PROGRAM:
#include<stdio.h>
int main()
{
int no_of_frames, no_of_pages, frames[10], pages[30], temp[10], flag1, flag2, flag3, i, j, k, pos,
max, faults = 0;
printf("Enter number of frames: ");
scanf("%d", &no_of_frames);
71
GNITC – SPECIAL BRANCH
72
GNITC – SPECIAL BRANCH
if(flag1 == 0)
{
for(j = 0; j < no_of_frames; ++j)
{
if(frames[j] == -1)
{
faults++;
frames[j] = pages[i];
flag2 = 1;
break;
}
}
}
if(flag2 == 0)
{
flag3 =0;
for(j = 0; j < no_of_frames; ++j)
{
temp[j] = -1;
for(k = i + 1; k < no_of_pages; ++k)
{
if(frames[j] == pages[k])
{
temp[j] = k;
break;
}
}
}
73
GNITC – SPECIAL BRANCH
if(flag3 ==0)
{
max = temp[0];
pos = 0;
for(j = 1; j < no_of_frames; ++j)
{
if(temp[j] > max)
{
max = temp[j];
pos = j;
}
}
}
frames[pos] = pages[i];
faults++;
74
GNITC – SPECIAL BRANCH
printf("\n");
for(j = 0; j < no_of_frames;
++j){ printf("%d\t", frames[j]);
}
}
return 0;
}
Output
VIVA QUESTIONS:
1. What is the Optimal Page replacement?
2. Explain when page replacement occurs?
3. Which is the best page replacement algorithm? Why?
4. Explain various page replacement algorithms?
5. What do you mean by page fault?
75