0% found this document useful (0 votes)
46 views79 pages

Operating System Lab Manual

OPERATING SYSTEM LAB MANUAL

Uploaded by

22wj8a6788
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)
46 views79 pages

Operating System Lab Manual

OPERATING SYSTEM LAB MANUAL

Uploaded by

22wj8a6788
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/ 79

GNITC – SPECIAL BRANCH

GURU NANAK INSTITUTIONS TECHNICAL CAMPUS (AUTONOMOUS)


SCHOOL OF ENGINEERING & TECHNOLOGY

LABORATORY MANUAL

Operating Systems Lab


B.TECH II Year-II Semester

LAB CODE: 22PC0DS10

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING – DS

AY: 2022-2023
GNITC – SPECIAL BRANCH

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING - AIML

LAB MANUAL FOR THE ACADEMIC YEAR 2022-23

LAB : OPERATING SYSTEMS LAB

LAB CODE : 22PC0DS10

YEAR II

SEMESTER II

STREAM : CSE - DS

DOCUMENT NO : GNITC–

VENUE : Guru Nanak Institute of Technical Campus

BLOCK : GNU Block

PREPARED BY : Mr. Ridwan Uz Zaman Pandit

VERIFIED BY

HOD – SPECIAL BATCH


GNITC – SPECIAL BRANCH

INDEX

SL.NO. CONTENTS

1. Programme Educational Objectives & Programme Outcomes

2. Department Vision & Mission

3. Lab Objective

4. Lab outcomes

5. Introduction About Lab

Guidelines to students
6. a) Standard Operating Procedure (SOP)
b) General guidelines

7. List of experiments as per the Atonoums curriculum

8. List of Additional Experiments

9. Text Books / Reference Books

Content of the experiment. Objective of the Experiment Hardware


& Software Requirements Pre- requisite
10.
Flow chart/ algorithm with inputs and outputs Program
Output Conclusion
GNITC – SPECIAL BRANCH

PROGRAMME EDUCATIONAL OBJECTIVES (PEOs)

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.

PROGRAMME OUTCOMES (POs)

Engineering Graduates will be able to:


1. Engineering knowledge: Apply the knowledge of mathematics, science, engineering
fundamentals, and an engineering specialization to the solution of complex engineering
problems.
2. Problem analysis: Identify, formulate, review 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 the public health and safety, and the cultural, societal, and environmental
considerations.

PROGRAMME SPECIFIC OUTCOMES (PSOs)

1. Ability to design, develop, test and debug software applications, evaluate and recognize potential
risks and provide innovative solutions.

2. Explore technical knowledge in diverse areas of Information Technology for upliftment of


society, successful career, entrepreneurship and higher studies.

VISION OF THE DEPARTMENT

To become a premier Computer Science and Engineering department by imparting high quality
education, ethical values, provide creative environment for innovation and global opportunities

MISSION OF THE DEPARTMENT

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

Awarding the marks for day to day evaluation:


 Total marks for day-to-day evaluation is 15 Marks as per JNTUH.
 These 15 Marks are distributed as:
Record 5 Marks

Experiment setup/program written and 5 Marks


execution

Result and Viva-Voce 5 Marks

Allocation of Internal Marks


Total marks for lab internal are 40 Marks as per JNTUH/GNITC.
These 40 Marks are distributed as:

Average of day to day evaluation marks : 15 Marks


Lab Mid exam : 10 Marks
Allocation of External Marks

 Total marks for lab external are 60 Marks as per AUTONOMOUS,


JNTUH.
 These 70 Marks are distributed as:
Program Written : 20 Marks
Program Execution and Result : 20 Marks
Viva-Voce : 20 Marks
Record : 10 Marks
Introduction about Lab

There are 60 systems installed in this Lab. Their configurations are as


follows:

 Processor : Intel(R) Pentium(R) Dual CPU


2.0GHz
 RAM : 4 GB
 Hard Disk : 500 GB
 Mouse : Optical Mouse
 Software: All systems are configured in DUAL BOOT mode i.e.,
Students can boot from Windows XP or Linux as per their lab
requirement. This is very useful for students because they are familiar
with different Operating Systems so that they can execute their
programs in different programming environments.
 Each student has a separate login for database access. Oracle 9i client
version is installed in all systems. On the server, an account for each
student has been created. This is very useful because students can
save their work (scenarios’, PL / SQL program data related projects,

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.

Standard Operating Procedure (SOP)


a) Explanation about the experiment by the concerned faculty using PPT covering
the following aspects:
1) Name of the experiment/Aim
2) Software/Hardware required
3) Commands with suitable Options
4) Test Data
5) Valid data sets
6) Limiting value sets
7) Invalid data sets
b) Writing of shell programs by the students
c) Compiling and execution of the program 90 mins.
Write-up in the Observation Book
The students will write the today’s experiment in the Observation book as per the
following format:
a) Name of the experiment/Aim
b) Software/Hardware required
c) Commands with suitable Options
d) Shell Programs/System call using C-Programs
e) Test Data
1. Valid data sets
2. Limiting value sets
3. Invalid data sets
f) Results for different data sets
g) Viva-Voce Questions and Answers
h) Errors observed (if any) during compilation/execution
i) Signature of the Faculty

2
GNITC – SPECIAL BRANCH

Guidelines to the Students


Disciplinary to be maintained by the students

 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.

Steps to perform experiment

 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.

Instructions to maintain the record

 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

OPERATING SYSTEMS LAB

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.

S.NO LIST OF EXPERIMENTS


Write a program to implement following process scheduling algorithms for a
given specification of CPU utilization, throughput, turnaround time, waiting
time, response time.
1 i. First Come First Serve
ii. Shortest Job First
iii. Priority
iv. Round Robin
Write programs using the I/O system calls of UNIX/LINUX operating system
2
(open, read, write, close,fcntl, seek, stat, opendir, readdir)
Write a C program to simulate Bankers Algorithm for Deadlock Avoidance and
3
Prevention
Write a C program to implement the Producer – Consumer problem using
4
semaphores usingUNIX/LINUX system calls.
Write C programs to illustrate the following IPC mechanisms a) Pipes b) FIFOs
5
c) Message Queues d) Shared Memory
Write C programs to simulate the following memory management techniques a)
6
Paging b)Segmentation B.Tech-Computer Science and Engineering
Write C programs to simulate Page replacement policies a) FCFS b) LRU c)
7
Optima

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

b) AIM: To Simulate the Shortest Job First 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
Theory:
Shortest job First: The criteria of this algorithm are which process having the smallest CPU
burst, CPU is assigned to that next process. If two process having the same CPU burst Time
FCFS is used to break the tie.
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 shortest burst 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,bt[10],t,n,wt[10],tt[10],w1=0,t1=0;
float aw,at;
clrscr();

9
GNITC – SPECIAL BRANCH

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++)
{
for(j=i;j<n;j++)
if(bt[i]>bt[j])
{

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

3) What are the dis-advantages of SJF Scheduling Algorithm?


4) What are the advantages of SJF Scheduling Algorithm?
5) Define CPU Scheduling algorithm?

11
GNITC – SPECIAL BRANCH

c) AIM: To Simulate the Round Robin CPU 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
Theory:
Round Robin: It is a primitive scheduling algorithm it is designed especially for timesharing
systems. In this, the CPU switches between the processes. When the time quantum expired, the
CPU switches to another job. A small unit of time called a quantum or time slice. A time
quantum is generally is a circular queue new processes are added to the tail of the ready queue.

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

c)Shortest job - first scheduling algorithm d)None of the above

15
GNITC – SPECIAL BRANCH

d) AIM: To Simulate the Priority 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
Theory:
Priority Scheduling: The cpu is allocated to the process with the highest priority. Equal priority
processes are scheduled in the FCFS order. Priorities are generally some fixed range of numbers
such as 0 to 409. The low numbers represent high priority

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;

printf(" \n job \t bt \t wt \t tat \t prior\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:

1. In which OS we would like to use Priority CPU scheduling.

2. How much CPU is allocated to Priority Scheduling.

3. How to calculate average waiting time?

4. How you can achieve Maximum CPU Utilization?

5. By using what algorithms we can find minimum and maximum time

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.

I/O System calls :


● open : used to open / create new files
syntax:
int open(const char *pathname, int flags, mode_t mode);
● read: used to read contents of an open file , returns the no of bytes read
syntax:
ssize_t read(int fd, void *buf, size_t count);
● write: used to write data to an open file , returns the no of bites written
syntax:
ssize_t write(int fd, void *buf, size_t count);
● close: used to close an open file
syntax:
int close(int fd);
● fcntl: used to change file status flag, lock files, setting file related attributes and behaviors
syntax:
int fcntl(int fd, int cmd, .../* arg */);

20
GNITC – SPECIAL BRANCH

● lseek: it is used to move the current position within the file


syntax:
off_t lseek(int fd, off_t offset, int whence);
● stat: used to obtain information about a file or file system
syntax:
int stat(const char *path, struct stat *buf);
● opendir: it is used to open a directory
◦ NOTE: the opendir used in the following programs is not a system call but a c library
function which accesses the opendir system call
◦ syntax of opendir():
DIR *opendir(const char *dirname);
● readdir: it is used to read the contents of a directory
◦ NOTE: the readdir used in the following programs is not a system call but a c library
function which accesses some system calls
◦ syntax of readdir():
struct dirent *readdir(DIR *dirp);

21
GNITC – SPECIAL BRANCH

2.1 : open , write , read , close a file


Aim: to perform open, read, write, close system calls
Algorithm:
1. declare variable fd , n , buffer
2. open a file you want to write to by giving necessary flags and permissions and assign it to fd
3. check if the file descriptor returned by open is valid, if not print an error message using perror
and exit the program
4. using the write function write the desired text to be entered
5. close the file using the close function
6. reopen the file using the open function and reading flags
7. check if the file descriptor returned by open is valid, if not print an error message using perror
and exit the program
8. read from the file into buffer using the read function and store the no of bytes read in n
9. check if the return value of read function is -1 if it is -1 print an error message using the perror
and exit program
10. Null-terminate the buffer by setting the n+1th element to '\0'.
11. print the contents of the buffer using printf
12. close the file using close function
13. exit the program by returning 0

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

write(fd, "Hello, world!\n", 14);


// Close the file
close(fd);
// Open the file for reading
fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
exit(1);
}

// Read from the file


n = read(fd, buffer, sizeof(buffer));
if (n == -1) {
perror("read");
exit(1);
}
// Null-terminate the buffer buffer[n]
= '\0';
printf("Read from file: \n%s", buffer);
// Close the file
close(fd);
return 0;

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

printf("User ID of owner: %u\n", (unsigned)file_stat.st_uid);


printf("Group ID of owner: %u\n", (unsigned)file_stat.st_gid);
printf("Device ID (if special file): %ld\n", (long)file_stat.st_rdev);

printf("Last access time: %s", (char*)ctime(&file_stat.st_atime)); // Cast to char*


printf("Last modification time: %s", (char*)ctime(&file_stat.st_mtime)); // Cast to char*
printf("Last status change time: %s", (char*)ctime(&file_stat.st_ctime)); // Cast to char*
return 0;
}

Output:

2.4: fcntl

Aim: to perform fcntl system call

Algorithm:

1. Declare variables fd and flags.


2. Prompt the user to enter a filename using printf.
3. Read the filename from the user using fgets.

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

// Get the current file status flags


flags = fcntl(fd, F_GETFL);
if (flags == -1)
{ perror("fcntl
(F_GETFL)");
exit(EXIT_FAILURE);
}
printf("File status flags before: %d\n", flags);

// Set the O_NONBLOCK flag to make the file descriptor non-blocking


flags |= O_NONBLOCK;
printf("File status flags after: %d\n", flags);
if (fcntl(fd, F_SETFL, flags) == -1)
{ perror("fcntl (F_SETFL)");
exit(EXIT_FAILURE);

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

2.5 : opendir , readdir


Aim: to perform opendir and readdir

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

1. if Request<=Need I go to step 2. Otherwise raise an error condition.


2. if Request<=Available go to step 3. Otherwise Pi must since the resources are available.
3. Have the system pretend to have allocated the requested resources to process Pi by modifying
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 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:

1. Differentiate deadlock avoidance and fragmentation


2. Tell me the real time example where this deadlock occurs?
3. How do we calculate the need for process?
4. What is the name of the algorithm to avoid deadlock?
5. Banker’s algorithm for resource allocation deals with
(A)Deadlock prevention. (B)Deadlock avoidance.
(C)Deadlock recovery. (D)Mutual exclusion

3.2 AIM: To Simulate BANKER’S ALGORITHM For Deadlock Prevention.


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
Theory:
Deadlock Prevention: Difference from avoidance is that here, the system itself is built in such a way
that there are no deadlocks. Make sure at least one of the 4 deadlock conditions is never satisfied. This
may however be even more conservative than the deadlock avoidance strategy.
ALGORITHM:
1. Start
2. Attacking Mutex condition: never grant exclusive access but this may not be possible for several
resources.
3. Attacking preemption: not something you want to do.
4. Attacking hold and wait for conditions: make a process hold at most 1 resource at a time make all the
requests at the beginning. All or nothing policy. If you feel, retry. eg. 2-phase locking
5. Attacking circular wait: Order all the resources. Make sure that the requests are issued in the correct
order so that there are no cycles present in the resource graph. Resources numbered 1 ... n. Resources
can be requested only in increasing order. ie. you cannot request a resource whose no is less than any
you may be holding.
6. Stop

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.

1. Initialize the semaphores mutex, empty, and full using sem_init.


2. Create two threads, one for the producer and one for the consumer, using pthread_create.
3. Wait for the threads to finish using pthread_join.
4. Destroy the semaphores using sem_destroy.
5. Exit the program.

The producer thread should do the following:

1. Declare a variable i and initialize it to 1.


2. While i is less than or equal to MAX_ITEMS, do the following:
a. If the buffer is full, print a message indicating that the producer is waiting.

b. Wait on the empty semaphore using sem_wait.

c. Wait on the mutex semaphore using sem_wait.

d. Add i to the buffer and print a message indicating that i has been produced.

e. Signal the mutex semaphore using sem_post.

f. Signal the full semaphore using sem_post.

g. Increment i.

h. Update the index in to point to the next available slot in the buffer.

i. Sleep for a random amount of time using usleep.

3. Set the production_active flag to 0.

The consumer thread should do the following:

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.

b. Wait on the full semaphore using sem_wait.

c. Wait on the mutex semaphore using sem_wait.


44
GNITC – SPECIAL BRANCH

d. Get the next item from the buffer and print a message indicating that i has been
consumed.

e. Signal the mutex semaphore using sem_post.

f. Signal the empty semaphore using sem_post.

g. Update the index out to point to the next available slot in the buffer.

h. Sleep for a random amount of time using usleep.

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;

// Introduce a random delay before producing the next item


int delay = rand() % 1000000; // Random delay in microseconds
usleep(delay); // Sleep for the specified time
}
production_active = 0;
}
void* consumer(void* arg)
{ int i;
while (1) {
if (isBufferEmpty()) {
if (!production_active) {
return NULL; // Exit if production is done and buffer is empty
}
printf("Buffer is empty, consumer is waiting.\n");
}
sem_wait(&full);
sem_wait(&mutex);
// remove item from buffer
i = buffer[out];
printf("Consumed %d\n", i);

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

Aim: write a c program to illustrate the IPC mechanism 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

5.3 message queues

Aim: write a c program to implement the inter process communication mechanism, message
queues

Algorithm:

1. Declare variables key, msgid, and message.


2. Generate a key using the ftok function with a path and identifier.\
3. Create a message queue using the msgget function with the generated key and flags, and
4. store the message queue ID in msgid.
5. Check if the message queue was created successfully. If not, print an error message and exit the
program.
6. Fork a new process using the fork function and store the process ID in pid.
7. Check if the fork was successful. If not, print an error message and exit the program.If pid is 0,
do the following (child process): a. Receive a message from the message queue us
8. ing the msgrcv function and store it in a message. b. Process the received message.
9. If pid is not 0, do the following (parent process): a. Set the message type in the message. b.
Prompt the user to enter a message. c. Read the message from the user and store it in the
message. d. Send the message to the message queue using the msgsnd function.
10. Exit the program.

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

key = ftok("/tmp", 65);


msgid = msgget(key, 0666 | IPC_CREAT);
struct msg_buffer message;
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {

msgrcv(msgid, &message, sizeof(message), 1, 0);


printf("Child received: %s\n", message.msg_text);
} else
{ message.msg_type =
1;
printf("Enter a message: ");
fgets(message.msg_text, sizeof(message.msg_text), stdin);
msgsnd(msgid, &message, sizeof(message), 0);
}
return 0;
}

Output:

54
GNITC – SPECIAL BRANCH

5.4 shared memory

Aim: write a c program to implement the interprocess communication mechanism, shared


memory

Algorithm

1. Generate a key using ftok.


2. Create a shared memory segment using shmget.
3. Attach to the shared memory segment using shmat.
4. Create two semaphores using sem_open.
5. Fork a new process using fork.
6. If pid is 0, wait for the parent to signal using sem_wait, read the message from shared memory,
detach from shared memory using shmdt, and signal the parent that the child has finished using
sem_post.
7. If pid is not 0, prompt the user to enter a message, write the message to shared memory, signal
the child to proceed using sem_post, wait for the child to finish using sem_wait, and detach from
shared memory using shmdt.
8. Close and unlink the semaphores using sem_close and sem_unlink.
9. Exit the program.

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);

sem_post(parent); // Signal the child to proceed


sem_wait(child); // Wait for the child to finish
shmdt(shmem); // Detach from shared memory after child process has finished
}
sem_unlink("/parent");
sem_unlink("/child");
return 0;
}

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:

AIM : Write a program to simulate the following memory management techniques:

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?

AIM: To Simulate Segmentation Technique of Memory Management


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: A Memory Management technique in which memory is divided into variable sized chunks
which can be allocated to processes. Each chunk is called a Segment.
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>
#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

printf(“Enter base value:”);


scanf(“%d”,&base);
printf(“Enter value for limit:”);
scanf(“%d”,&limit);
insert(p,base,lmit,seg);
}
}
while(seg!=-1)
printf(“Enter offset:”);
scanf(“%d”,&offset);
printf(“Enter bsegmentation number:”);
scanf(“%d”,&seg);
c=find(p,seg);
s=search(p,seg);
if(offset<c)
{
physical=s+offset;
printf(“Address in physical memory %d\n”,physical);
}
else
{
printf(“error”);
}
}

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

WEEK-7: Write C programs to simulate the following Page Replacement Techniques:

a) FIFO b) LRU c) Optimal


AIM: To Simulate FIRST IN FIRST OUT Page Replacement Algorithm
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:
a) FIFO (First in First Out) algorithm: FIFO is the simplest page replacement algorithm,
the idea behind this is, “Replace a page that page is oldest page of main memory” or
“Replace the page that has been in memory longest”. FIFO focuses on the length of time a
page has been in the memory rather than how much the page is being used.

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 4. If the current page is present in the memory, do nothing.

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 7. Increment the page faults.

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]);
}
}

printf("\n\n\t\t No.of pages faults...%d",pf);


getch();
}
OUTPUT:

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

AIM: To Simulate LEAST RECENTLY USED Page Replacement Algorithm


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:
b) LRU (Least Recently Used ): the criteria of this algorithm is “Replace a page that has
been used for the longest period of time”. This strategy is the page replacement algorithm
looking backward in time, rather than forward.

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

AIM: To Simulate LEAST FREQUENTLY USED Page Replacement Algorithm


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:
c) OPTIMAL Page Replacement:

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

printf("Enter number of pages: ");


scanf("%d", &no_of_pages);

printf("Enter page reference string: ");

for(i = 0; i < no_of_pages; ++i)


{
scanf("%d", &pages[i]);
}

for(i = 0; i < no_of_frames; ++i)


{
frames[i] = -1;
}

for(i = 0; i < no_of_pages; ++i)


{
flag1 = flag2 = 0;

for(j = 0; j < no_of_frames; ++j)


{
if(frames[j] == pages[i])
{
flag1 = flag2 = 1;
break;
}
}

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

for(j = 0; j < no_of_frames; ++j)


{
if(temp[j] == -1)
{
pos = j;
flag3 = 1;
break;
}
}

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]);
}
}

printf("\n\nTotal Page Faults = %d", faults);

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

You might also like