751abbdfOS CO204 Sample Lab File 2023 (For Prof. Anil Singh Parihar)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 37

DELHI TECHNOLOGICAL UNIVERSITY

(Formerly Delhi College of Engineering)


Shahbad Daulatpur, Bawana Road, Delhi- 110042

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING

Operating System Design Laboratory


Subject Code: CO-204

SUBMITTED TO: SUBMITTED BY:


Prof. Anil Singh Parihar Madhav Gupta
B. Tech CSE 2nd year
Department of Computer (Semester-4)
Science and Engineering Roll No:2K21/CO/262

1
2
INDEX

S No. Topic Date Sign

1 Basic Linux Commands. 11/1/2023

2 Basic UNIX Commands. 18/1/2023

3 To Write a C Program to implement process system calls 25/01/2023

4 To Write a C Program to implement I/O system calls 25/01/2023

5 To WAP to implement CPU scheduling for Round Robin and Shortest 01/02/2023
Job First.

6 To WAP to implement CPU scheduling for First Come First Serve and 01/03/2023
Priority Scheduling

7 To implement producer/consumer problem using semaphores. 22/03/2023

8 To write a program that implements inter-process communication 29/03/2023


(IPC) using pipe processing.

9 To implement first fit for memory management 29/03/2023

10 To implement best fit for memory management 12/04/2023

11 To write a program performs file manipulation. 12/04/2023

12 To write a program for file manipulation for displays the file and 12/04/2023
directory in memory

13 To Simulate FIFO page replacement algorithms 19/04/2023

14 To Simulate LRU page replacement algorithms 19/04/2023

15 To create program for optimal page replacement algorithms. 19/04/2023

16 To Simulate Algorithm for Deadlock prevention 19/04/2023

3
EXPERIMENT 1
OBJECTIVE
Basic Linux Commands.

THEORY
sudo: allows a user to execute a command with root/administrator privileges.
pwd: prints the current working directory.
cd: changes the current working directory.
ls: lists the files and directories in the current directory.
cat: displays the contents of a file on the terminal.
cp: copies a file or directory from one location to another.
mv: moves or renames a file or directory.
mkdir: creates a new directory.
rmdir: removes an empty directory.
rm: removes a file or directory (use with caution!).
touch: creates an empty file or updates the modification time of an existing file.
diff: compares two files and shows the differences.
tar: creates or extracts a compressed archive of files and directories.
find: searches for files and directories based on certain criteria.
grep: searches for a pattern or text string in a file or output.
df: displays the available disk space on the file system.
du: displays the disk usage of files and directories.
head: displays the first 10 lines of a file.
tail: displays the last 10 lines of a file.

LEARNING OUTCOME
The following Basic LINUX commands are familiarized and implemented.

1
EXPERIMENT 2
OBJECTIVE
Basic UNIX Commands.

THEORY
chmod: changes file or directory permissions
chown: changes the owner of a file or directory
jobs: displays active jobs in the shell
kill: terminates a process by ID or name
ping: tests network connectivity between two hosts
wget: downloads files from the internet
uname: displays system information
top: displays system resource usage in real-time
history: displays a list of previously executed commands
man: displays the manual pages for a command
echo: prints text to the terminal
zip: compresses files into a zip archive
unzip: extracts files from a zip archive
hostname: displays the hostname of the current system
useradd: creates a new user account
userdel: deletes a user account
apt-get: package manager for Debian-based Linux systems
nano: text editor with a command-line interface
vi: text editor with a command-line interface
jed: text editor with a graphical user interface
alias: creates a shortcut for a command or series of commands
unalias: removes a previously created alias
su: switches to a different user account or root user
htop: displays system resource usage in real-time with a more user-friendly interface than top
ps: displays a list of currently running processes
vim: advanced text editor with a command-line interface

LEARNING OUTCOME
The following Basic UNIX commands are familiarized and implemented.

2
EXPERIMENT 3
OBJECTIVE
To Write a C Program to implement process system calls

PROCEDURE
1. Start the program.
2. Declare the pid and get the pid by using the getpid() method.
3. Create a child process by calling the fork() system call
4. Check if(pid==0)
o then print the child process id and then print the parent process value.
o Else print.
5. Stop the program

CODE OUTPUT
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
void main()
{
int pid;
pid=fork();
if (pid==0)
{
printf("This is a child Having ID: %d\n", getpid());
printf("This is the ID of my parent: %d\n\n", getppid());
exit(0);
}
else if (pid>0)
{
printf("This is the ID of my child: %d\n",pid);
printf("This is a parent Having ID: %d\n\n",getpid());
exit(0);
}
else if (pid<0)
{
printf("fork failed");
exit(1);
}
}

LEARNING OUTCOME
Thus the process system call program was executed and verified successfully.

3
EXPERIMENT 4
OBJECTIVE
To Write a C Program to implement I/O system calls

THEORY
1. Start the program.
2. open a file for
O_RDWR for R/W,
O_CREATE for creating a file ,
O_TRUNC for truncating a file
3. Using getchar(), read the character and stored in the string[] array
4. The string [] array is write into a file close it.
5. Then the first is opened for read only mode and read the characters and displayed It and close the
file
6. Stop the program

CODE
#include <stdio.h> #include <unistd.h> #include <string.h> #include <fcntl.h>

int main() OUTPUT


{
int fd[2];
char buf1[25] = "Test Text: \n";
char buf2[50];

fd[0] = open("file1", O_RDWR);


fd[1] = open("file2", O_RDWR);

write(fd[0], buf1, strlen(buf1));


printf("\n Enter Text: ");

scanf("%s", buf1);
write(fd[0], buf1, strlen(buf1));

lseek(fd[0], SEEK_SET, 0);


read(fd[0], buf2, sizeof(buf2));
write(fd[1], buf2, strlen(buf2));

close(fd[0]);
close(fd[1]);
printf("\n");
return 0;
}
LEARNING OUTCOME
Thus the I/O system call program was executed and verified successfully.

4
EXPERIMENT 5
OBJECTIVE
To WAP to implement CPU scheduling for Round Robin and Shortest Job First.

1. Round Robin

ALGORITHM
Round Robin scheduling is a CPU scheduling algorithm that ensures that all processes get an equal
amount of CPU time. In this algorithm, each process is assigned a fixed time quantum, and the CPU
switches between processes when the quantum expires. If a process does not complete its execution
within the assigned time quantum, it is preempted, and the CPU switches to the next process in the
queue. This algorithm is commonly used in time-sharing systems, where multiple users share a single
CPU.

CODE
#include<iostream>
using namespace std;
void findWaitingTime(int processes[], int n, int bt[], int wt[], int quantum)
{
int rem_bt[n];
for (int i = 0 ; i < n ; i++)
rem_bt[i] = bt[i];
int t = 0;
while (true)
{
bool done = true;
for (int i = 0 ; i < n; i++){
if (rem_bt[i] > 0) {
done = false;
if (rem_bt[i] > quantum)
t += quantum;
rem_bt[i] -= quantum;
}
else{
t = t + rem_bt[i];
wt[i] = t - bt[i];
rem_bt[i] = 0;
}
}
}
if (done == true break;
}
}
void findTurnAroundTime(int processes[], int n, int bt[], int wt[], int tat[])
{
for (int i = 0; i < n ; i++)
tat[i] = bt[i] + wt[i];
}

5
void findavgTime(int processes[], int n, int bt[], int quantum)
{
int wt[n], tat[n], total_wt = 0, total_tat = 0;
findWaitingTime(processes, n, bt, wt, quantum);
findTurnAroundTime(processes, n, bt, wt, tat);
cout << "ROUND ROBIN SCHEDULING ALGORITHM" <<endl;
cout << "PN "<< " \tBT " << " \t WT " << " \tTAT\n";
for (int i=0; i<n; i++)
{
total_wt = total_wt + wt[i];
total_tat = total_tat + tat[i];
cout << " " << i+1 << "\t" << bt[i] <<"\t " << wt[i] <<"\t " << tat[i] <<endl;
}
cout << "Average waiting time = " << (float)total_wt / (float)n;
cout << "\nAverage turn around time = " << (float)total_tat / (float)n;
}

int main()
{
int processes[] = { 1, 2, 3};
int n = sizeof processes / sizeof processes[0];
int burst_time[] = {10, 5, 8};
int quantum = 2;
findavgTime(processes, n, burst_time, quantum);
return 0;
}
OUTPUT

LEARNING OUTCOME
Thus the Round Robin program was executed and verified successfully.

6
2. Shortest Job First

ALGORITHM
Shortest Job First is a CPU scheduling algorithm that selects the process with the shortest burst time
from the ready queue to execute next. This algorithm can minimize the average waiting time of
processes. The drawback of this algorithm is that the burst time of a process is not known until it
starts executing. Therefore, it is difficult to implement SJF in practice.

PROGRAM
#include <bits/stdc++.h>
using namespace std;
struct Process {
int pid;
int bt;
int art;
};
void findTurnAroundTime(Process proc[], int n, int wt[], int tat[]) {
for (int i = 0; i < n; i++)
tat[i] = proc[i].bt + wt[i];
}
void findWaitingTime(Process proc[], int n, int wt[]) {
int rt[n];
for (int i = 0; i < n; i++)
rt[i] = proc[i].bt;
int complete = 0, t = 0, minm = INT_MAX;
int shortest = 0, finish_time;
bool check = false;
while (complete != n) for (int j = 0; j < n; j++) {
for (int j = 0; j <n ;j++){
if ((proc[j].art <= t) && (rt[j] < minm) && rt[j] > 0) {
minm = rt[j];
shortest = j;
check = true;
}}
if (check == false) {
t++;
continue;
}
rt[shortest]--;
minm = rt[shortest];
if (minm == 0) minm = INT_MAX;
if (rt[shortest] == 0) {
complete++;
check = false;
finish_time = t + 1;
wt[shortest] = finish_time - proc[shortest].bt - proc[shortest].art;
if (wt[shortest] < 0)
wt[shortest] = 0;
}
7
t++;
}
}
void findavgTime(Process proc[], int n) {
int wt[n], tat[n], total_wt = 0, total_tat = 0;
findWaitingTime(proc, n, wt);
findTurnAroundTime(proc, n, wt, tat);
cout << "Processes " << " Burst time " << " Waiting time " << " Turn around time\n";
for (int i = 0; i < n; i++) {
total_wt = total_wt + wt[i];
total_tat = total_tat + tat[i];
cout << " " << proc[i].pid << "\t\t" << proc[i].bt << "\t\t " << wt[i] << "\t\t " << tat[i] <<
endl;
}
cout << "\nAverage waiting time = " << (float)total_wt / (float)n;
cout << "\nAverage turn around time = " << (float)total_tat / (float)n;
}

int main() {
Process proc[] = { { 1, 5, 1 }, { 2, 3, 1 }, { 3, 6, 2 }, { 4, 5, 3 } };
int n = sizeof(proc) / sizeof(proc[0]);
findavgTime(proc, n);
return 0;
}

OUTPUT

LEARNING OUTCOME
Thus the SJF program was executed and verified successfully

8
EXPERIMENT 6
OBJECTIVE
To WAP to implement CPU scheduling for First Come First Serve and Priority Scheduling

1. First Come First Serve

ALGORITHM
First Come First Serve is a CPU scheduling algorithm where the process that arrives first is served
first. In this algorithm, the CPU executes the process that has been waiting in the ready queue for the
longest time. The main disadvantage of this algorithm is that it may lead to long waiting times for
processes with long burst times.

CODE
void findWaitingTime(int processes[], int n, int bt[], int wt[])
{
wt[0] = 0;
for (int i = 1; i < n ; i++ )
wt[i] = bt[i-1] + wt[i-1] ;
}
void findTurnAroundTime( int processes[], int n, int bt[], int wt[], int tat[])
{
for (int i = 0; i<n ;i++)
tat[i] = bt[i] + wt[i];
}
void findavgTime(int processes[], int n, int bt[])
{
int wt[n], tat[n], total_wt = 0, total_tat = 0;
findWaitingTime(processes, n, bt, wt);
findTurnAroundTime(processes, n, bt, wt, tat);
cout << "First Come First Serve Scheduling Algorithm" <<endl;
cout << "PID "<< " \tBT " << "\tWT " << "\tTAT\n" ;
for (int i=0; i<n; i++)
{
total_wt = total_wt + wt[i];
total_tat = total_tat + tat[i];
cout << i+1 << "\t" << bt[i] <<"\t" << wt[i] <<"\t" << tat[i] <<endl;
}
cout << "Average waiting time = " << (float)total_wt / (float)n;
cout << "\nAverage turn around time = " << (float)total_tat / (float)n;
}
int main()
{
int processes[] = { 1, 2, 3};
int n = sizeof processes / sizeof processes[0];
int burst_time[] = {10, 5, 8};
findavgTime(processes, n, burst_time);
return 0;
}

9
OUTPUT

LEARNING OUTCOME
Thus the FCFS program was executed and verified successfully

10
2. Priority Scheduling

ALGORITHM
Priority Scheduling is a CPU scheduling algorithm where each process is assigned a priority level,
and the process with the highest priority is executed first. Priority levels can be assigned based on
process characteristics such as execution time, deadline, or importance. In preemptive priority
scheduling, a running process can be preempted by a higher-priority process. In non-preemptive
priority scheduling, the currently running process cannot be preempted by a higher-priority process.
This algorithm can result in starvation of low-priority processes, where high-priority processes are
continually served, and low-priority processes have to wait for an extended period.

CODE
struct process
{
int at,bt,pr,pno;
};
process proc[50];
bool comp(process a,process b)
{
if(a.at == b.at) return a.pr<b.pr;
else return a.at<b.at;
}
void get_wt_time(int wt[])
{
int service[50];
service[0] = proc[0].at;
wt[0]=0;
for(int i=1;i<totalprocess;i++)
{
service[i]=proc[i-1].bt+service[i-1];
wt[i]=service[i]-proc[i].at;
if(wt[i]<0) wt[i]=0;
}
}

void get_tat_time(int tat[],int wt[])


{
for(int i=0;i<totalprocess;i++) tat[i]=proc[i].bt+wt[i];
}

void findgc()
{
int wt[50],tat[50];
double wavg=0,tavg=0;
get_wt_time(wt);
get_tat_time(tat,wt);
int stime[50],ctime[50];
stime[0] = proc[0].at;
ctime[0]=stime[0]+tat[0];
for(int i=1; i<totalprocess; i++)
11
{
stime[i]=ctime[i-1];
ctime[i]=stime[i]+tat[i]-wt[i];
}
cout<<"Priority Scheduling Algorithm"<<endl;
cout<<"PID\tST\tFT\tTAT\tWT"<<endl;
for(int i=0;i<totalprocess;i++)
{
wavg += wt[i];
tavg += tat[i];
cout<<proc[i].pno<<"\t"<< stime[i]<<"\t"<<ctime[i]<<"\t"<< tat[i]<<"\t"<<wt[i]<<endl;
}
cout<<"Average Waiting Time : ";
cout<<wavg/(float)totalprocess<<endl;
cout<<"Average Turnaround Time : ";
cout<<tavg/(float)totalprocess<<endl;
}
int main()
{
int arrivaltime[] = { 1, 2, 3, 4, 5 };
int bursttime[] = { 3, 5, 1, 7, 4 };
int priority[] = { 3, 4, 1, 7, 8 };

for(int i=0;i<totalprocess;i++)
{
proc[i].at=arrivaltime[i];
proc[i].bt=bursttime[i];
proc[i].pr=priority[i];
proc[i].pno=i+1;
}
sort(proc,proc+totalprocess,comp);
findgc();
return 0;
}

OUTPUT

LEARNING OUTCOME
Thus the Priority Scheduling program was executed and verified successfully

12
EXPERIMENT 7
OBJECTIVE
To implement producer/consumer problem using semaphores.

THEORY
The producer-consumer problem is a classic synchronization
problem in computer science where producers generate data and
put it in a shared buffer while consumers remove data from the
buffer and process it. Semaphores can be used to solve this
problem efficiently and scalably. Two semaphores, one to track
the number of empty slots and one to track the number of filled
slots in the buffer, are used along with a mutex semaphore to
ensure that only one process can access the buffer at a time.
The producer process checks the empty semaphore and acquires
the mutex semaphore to add data to the buffer, while the consumer process c hecks the full semaphore
and acquires the mutex semaphore to remove data from the buffer. By following these rules, the
producer and consumer processes do not interfere with each other, and the buffer is accessed by only
one process at a time. The semaphore-based solution to the producer-consumer problem is an efficient
and scalable way to handle multiple producers and consumers.

PROCEDURE
1. Declare variable for producer & consumer as pthread-t-tid produce tid consume.
2. Declare a structure to add items, semaphore variable set as struct.
3. Read number the items to be produced and consumed.
4. Declare and define semaphore function for creation and destroy.
5. Define producer function.
6. Define consumer function.
7. Call producer and consumer.
8. Stop the execution.

CODE
#include<stdio.h>
void wait(int S) {
while (S <= 0); // busy wait
S--;
}
void signal(int S){
S++;
}
int main()
{
int n;
printf("Enter Buffer Size: ");
scanf("%d", n);
int buffer[n], produce, consume;
int mutex = 1; int choice = 0; int in = 0; int out = 0;
int bufsize = 10;
while (choice != 3)
13
{
printf("\nMENU \n 1. Produce \n 2. Consume \n 3. Exit");
printf("\nChoice: ");
scanf("%d", & choice);
switch (choice)
{
case 1:
if((mutex == 1) && (in + 1) % bufsize != out)
{
wait(mutex);
printf("Enter Produced Value: ");
scanf("%d", & produce);
buffer[in] = produce;
in = (in + 1) % bufsize;
signal(mutex);
}
else
printf("Buffer Full");
break;
case 2:
if (in == out) printf("\nBuffer Empty");
else if(mutex == 1)
{
wait(mutex);
consume = buffer[out];
printf("\n%d is Comsumed", consume);
out = (out + 1) % bufsize;
signal(mutex);
}
break;
} } }
OUTPUT

LEARNING OUTCOME
Thus, the Producer-Consumer program was executed and verified successfully.

14
EXPERIMENT 8
OBJECTIVE
To write a program that implements inter-process communication (IPC) using pipe processing.

THEORY
Inter-Process Communication (IPC) refers to the mechanism by which different processes running on
a system can exchange information and coordinate with each other. One common way to achieve IPC
is through the use of pipes.
A pipe is a unidirectional data
channel that connects two
processes. One process writes data
to the pipe, and the other process
reads the data from the pipe. Pipes
are typically used for communication between a parent process and its child processes, but they can
also be used between unrelated processes.To create a pipe, the pipe() system call is used. This call
creates a pair of file descriptors, one for reading and one for writing, that can be used to communicate
between the two processes. The parent process creates the pipe before forking a child process. The
child process then inherits the file descriptors of the parent process and uses them to communicate
through the pipe.

PROCEDURE
1. Start the program.
2. Declare the variables.
3. Read the choice.
4. Create a piping processing using IPC.
5. Assign the variable lengths
6. “strcpy” the message lengths.
7. To join the operation using IPC.
8. Stop the program.

CODE
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h>
int main()
{
int fd[2],n;
char buffer[100];
pid_t p;

pipe(fd); // pipe with ends fd[0] and fd[1]


p=fork();

if(p>0) //parent
{
printf("Value is being passed to Child from Parent...\n");
write(fd[1],"HelloWorld\n",10); //fd[1] is the write end of the pipe
}
else // child
{
printf("Recieved value being printed by child:\n");
15
n=read(fd[0],buffer,10); //fd[0] is the read end of the pipe
write(1,buffer,n);
}
}
OUTPUT

LEARNING OUTCOME
Thus, the Piping process using IPC program was executed and verified successfully.

16
EXPERIMENT 9
OBJECTIVE
To implement first fit for memory management.

THEORY
The First Fit algorithm is a memory allocation technique
where the first available memory block that is large
enough to accommodate the process is selected. It is a
simple and efficient algorithm, and the overhead of
searching for a suitable block of memory is minimal.
However, it can lead to memory fragmentation, which
can cause wastage of memory.
For first fit, allocate the process to first possible segment
which is free and set the personnel slap as ‘1’. So that
none of process to be allocated to segment which is
already allocated and vice versa.

PROCEDURE
1. Start the program.
2. Get the segment size, number of processes to be allocated, and their corresponding sizes.
3. Initialize the necessary variables:
• Define the maximum segment size as max.
• Declare the arrays frag, b, f, bf, and ff with a size of max.
• Set all elements of bf to 0 to indicate that all segments are free.
4. For each process to be allocated, do the following:
• Loop through all segments:
• If the segment is free (bf[j] == 0), check if it can accommodate the process (b[j]
>= size[i]).
• If it can, allocate the process to the segment (ff[i] = j) and mark the
segment as allocated (bf[j] = 1).
• Calculate the fragmentation (frag[i] = b[j] - size[i]).
• Break out of the loop.
• If no segment is found, set ff[i] = -1 to indicate that the process could not be
allocated.
5. Print the allocation details for each process:
• File number
• File size
• Block number
• Block size
• Fragmentation
6. Stop the program.

CODE
#include <stdio.h>
#define max 25

17
void main()
{
int frag[max], b[max], f[max], i, j, nb, nf, temp;
static int bf[max], ff[max];
printf("\n\tMemory Management Scheme - First Fit");
printf("\nEnter the number of blocks: "); scanf("%d", &nb);
printf("Enter the number of files: "); scanf("%d", &nf);
printf("\nEnter the size of the blocks: \n");
for (i = 1; i <= nb; i++)
printf("Block %d:", i);
scanf("%d", &b[i]);
}

printf("Enter the size of the files : \n");


for (i = 1; i <= nf; i++){
printf("File %d:", i);
scanf("%d", &f[i]);
}
for (i = 1; i <= nf; i++){
for (j = 1; j <= nb; j++){
if (bf[j] != 1){
temp = b[j] - f[i];
if (temp >= 0)
{
ff[i] = j;
break;
}
}
}
frag[i] = temp;
bf[ff[i]] = 1;
}
printf("\nFile_no:\tFile_size :\tBlock_no:\tBlock_size:\tFragement");
for (i = 1; i <= nf; i++)
printf("\n%d\t\t%d\t\t%d\t\t%d\t\t%d", i, f[i], ff[i], b[ff[i]], frag[i]);
}
OUTPUT

LEARNING OUTCOME
The First Fit Algorithm for Memory Management is executed Successfully.

18
EXPERIMENT 10
OBJECTIVE
To implement best fit for memory management.

THEORY
The Best Fit algorithm is a memory allocation technique
that aims to allocate the process to the smallest possible
free memory block that can accommodate it. This
algorithm searches for the best-fit block of memory that
minimizes the amount of leftover space after the process
is allocated.
The Best Fit algorithm starts by searching the entire list
of free memory blocks to find the smallest block that is
large enough to accommodate the process. If no block is
found, the algorithm continues searching until it finds a
block that is just large enough to fit the process. The
algorithm then allocates the process to that block and
marks the block as allocated.

PROCEDURE
1. Start the program.
2. Get the segment size, number of processes to be allocated, and their corresponding sizes.
3. Initialize the necessary variables:
• Define the maximum segment size as max.
• Declare the arrays frag, b, f, bf, and ff with a size of max.
• Set all elements of bf to 0 to indicate that all segments are free.
4. For each process to be allocated, do the following:
• Loop through all segments:
• If the segment is free (bf[j] == 0), check if it can accommodate the process (b[j]
>= size[i]).
• If it can, calculate the fragmentation (frag[i] = b[j] - size[i]).
• If the fragmentation is less than the current lowest fragmentation (frag[i]
< lowest), set ff[i] = j and update lowest to the new lowest
fragmentation.
• If no segment is found, set ff[i] = -1 to indicate that the process could not
be allocated.
• Mark the segment as allocated (bf[ff[i]] = 1).
5. Print the allocation details for each process:
• File number
• File size
• Block number
• Block size
• Fragmentation
6. Stop the program.

19
CODE
#include <stdio.h>
#define max 25
void main()
{
int frag[max], b[max], f[max], i, j, nb, nf, temp, lowest = 10000;
static int bf[max], ff[max];
printf("\nEnter the number of blocks:");
scanf("%d", &nb);
printf("Enter the number of files:");
scanf("%d", &nf);
printf("\nEnter the size of the blocks:-\n");
for (i = 1; i <= nb; i++){
printf("Block %d:", i);
scanf("%d", &b[i]);
}
printf("Enter the size of the files:-\n");
for (i = 1; i <= nf; i++){
printf("File %d:", i);
scanf("%d", &f[i]);
}
for (i = 1; i <= nf; i++){
for (j = 1; j <= nb; j++){
if (bf[j] != 1) {
temp = b[j] - f[i];
if (temp >= 0)
if (lowest > temp) {
ff[i] = j;
lowest = temp;
}}}
frag[i] = lowest; bf[ff[i]] = 1; lowest = 10000;
}
printf("\nFile_no \tFile_size \tBlock_no \tBlock_size \tFragment");
for (i = 1; i <= nf && ff[i] != 0; i++)
printf("\n%d\t\t%d\t\t%d\t\t%d\t\t%d", i, f[i], ff[i], b[ff[i]], frag[i]);
}
OUTPUT

LEARNING OUTCOME
The Best Fit Algorithm for Memory Management is executed Successfully.

20
EXPERIMENT 11
OBJECTIVE
To write a program performs file manipulation.

THEORY
File manipulation is an essential part of any operating system. File manipulation refers to the process
of creating, reading, writing, and modifying files on a file system. These operations are performed
using system calls provided by the operating system.
The "open" system call is used to open an existing file on the file system. This system call takes the
file name and the access mode as arguments. If the file is opened successfully, the system call returns
a file descriptor, which is a non-negative integer that is used to identify the opened file.
The "creat" system call is used to create a new file on the file system. This system call takes the file
name and the file permission as arguments. If the file is created successfully, the system call returns a
file descriptor, which is a non-negative integer that is used to identify the created file.
The "read" system call is used to read data from an opened file. This system call takes the file
descriptor, buffer address, and the number of bytes to be read as arguments. If the read operation is
successful, the system call returns the number of bytes read. If the end of the file is reached, the
system call returns zero.
The "write" system call is used to write data to an opened file. This system call takes the file
descriptor, buffer address, and the number of bytes to be written as arguments. If the write operation
is successful, the system call returns the number of bytes written.
The "close" system call is used to close an opened file. This system call takes the file descriptor as an
argument. If the file is closed successfully, the system call returns zero.
The "stat" system call is used to retrieve the file attributes such as user ID, access time, modification
time, inode number, and file permissions. This system call takes the file name and a structure pointer
as arguments. The structure pointer is used to store the file attributes.

PROCEDURE
1. Begin the program.
2. Declare the necessary arguments for file open and file creation.
3. Open the file specified in the first argument using the "open" system call, and check if it is
opened successfully.
4. Create a new file with the specified name in the second argument using the "create" system
call, and check if it is created successfully. Set the file permission to 0777.
5. If the file is not created successfully, display an error message indicating the failure.
6. Read the contents of the source file using the "read" system call and store it in a buffer of size
100 bytes.
7. Write the contents of the buffer to the destination file using the "write" system call, and check
if the write operation was successful.
8. While reading and writing the file contents, if there is any error, close the files using the
"close" system call.
9. Get the file attributes such as user ID, access time, modification time, inode number, and file
permissions using the "stat" system call.
10. Print the file attributes.
11. Close the files using the "close" system call.
12. End the program.
21
CODE
#include <stdio.h> #include <sys/stat.h> #include <time.h>
int main(int argc, char *argv[]){
char buf[100];
struct stat file_stat;
int source_fd, destination_fd, bytes_read;
// Open the source file
source_fd = open(argv[1], 0);
// Create the destination file
destination_fd = creat(argv[2], 0777);
// Check if the destination file is created successfully
if (destination_fd == -1){
printf("Error: Failed to create the file!\n");
return -1;
}
// Read the contents of the source file and write them to the destination file
while ((bytes_read = read(source_fd, buf, sizeof(buf))) > 0){
if (write(destination_fd, buf, bytes_read) != bytes_read){
printf("Error: Failed to write to the file!\n");
close(source_fd);
close(destination_fd);
return -1;
}
}
// Get file attributes
stat(argv[2], &file_stat);
// Print the file attributes
printf("\nUID for file: %d\nFile access time: %sFile modified time: %sFile inode number:
%d\nFile permissions: %o\n", file_stat.st_uid, ctime(&file_stat.st_atime),
ctime(&file_stat.st_mtime), file_stat.st_ino, file_stat.st_mode);
// Close the files
close(source_fd);
close(destination_fd);
return 0;
}
OUTPUT

LEARNING OUTCOME
Thus the File Manipulation program was executed and verified successfully.

22
EXPERIMENT 12
OBJECTIVE
To write a program for file manipulation for displays the file and directory in memory

THEORY
Program for file manipulation that displays the files and directories present in the current directory in
memory can be accomplished using the opendir(), readdir(), and closedir() functions provided by
the dirent.h header file.
The opendir() function is used to open a directory and returns a pointer to a directory stream. The
function takes a single argument, which is the name of the directory to be opened. In this case, the
. argument is used to open the current directory.
The readdir() function is used to read the next directory entry from the directory stream. The
function takes a single argument, which is a pointer to a directory stream, and returns a pointer to a
struct dirent that contains information about the directory entry. The readdir() function is called
repeatedly in a loop to read each directory entry in turn.
The closedir() function is used to close the directory stream once all of the directory entries have
been read. The function takes a single argument, which is a pointer to a directory stream.

PROCEDURE
1. Start the program.
2. Include the necessary header files, dirent.h and stdio.h.
3. Define the main function that returns an integer.
4. Declare a pointer variable for the directory stream, a pointer variable for the directory entry.
5. Use the opendir() function to open the current directory and assign the directory stream
pointer to the directory_pointer variable.
6. If the directory stream pointer is not equal to NULL, it indicates that the directory was
successfully opened.
7. Use a while loop to iterate through each directory entry using the readdir() function and
assign the directory entry pointer to the entry variable.
8. Inside the while loop, use the printf() function to display the name of the current directory
entry using the d_name member of the struct dirent pointed to by the entry pointer.
9. After the while loop, use the closedir() function to close the directory stream pointed to by
the directory_pointer variable.
10. End the program by returning 0 from the main function.

23
CODE
#include <dirent.h>
#include <stdio.h>

int main(void)
{
DIR *directory_pointer; // Pointer to directory stream
struct dirent *entry; // Pointer to directory entry
// Open the current directory
directory_pointer = opendir(".");
if (directory_pointer != NULL)
{
// Read the directory entries
while ((entry = readdir(directory_pointer)) != NULL)
{
// Display the name of each entry
printf("%s\n", entry->d_name);
}
// Close the directory stream
closedir(directory_pointer);
}
return 0;
}

OUTPUT

LEARNING OUTCOME
Thus the File Manipulation program was executed and verified successfully.

24
EXPERIMENT 13
OBJECTIVE
To Simulate FIFO page replacement algorithms

THEORY
FIFO algorithm works on the principle of first come, first serve. In this algorithm, the page that is
brought into memory first is the first one to be replaced when a page fault occurs. This algorithm is
simple to implement and requires only a queue data structure to maintain the order of pages in
memory. However, it suffers from a major disadvantage, known as the Belady's anomaly, which
means that the page fault rate can increase with an increase in the number of page frames allocated.

PROCEDURE
1. Start the program
2. Prompt the user to enter the number of frames
3. Prompt the user to enter the number of pages
4. Prompt the user to enter the page numbers
5. Initialize all the elements in the frame array to -1
6. Loop through each page in the reference string:
a. Set a variable named page_found to 0
b. Get the current page number from the reference string
c. Loop through each frame:
i. Check if the current page number is already in the frame
ii. If it is, set page_found to 1 and break out of the loop
d. If page_found is still 0, add the current page to the frame array in the first available slot (based
on FIFO order)
i. Increment the number of page faults
e. Print the current reference string and the current state of the page frames
7. Print the total number of page faults
8. End the program

CODE
#include <stdio.h> #define MAX_FRAMES 50
int main() {
int frames[MAX_FRAMES];
int reference[MAX_FRAMES];
int num_frames, num_references;
int num_page_faults = 0;
int frame_index = 0;
printf("FIFO Page Replacement Algorithm\n\n");
// Read input from user
printf("Enter the number of frames: "); scanf("%d", &num_frames);
printf("Enter the size of reference string: "); scanf("%d", &num_references);
printf("Enter the reference string (separated by space): ");
for (int i = 0; i < num_references; i++)
scanf("%d", &reference[i]);

// Initialize all frames to -1, indicating they are empty


for (int i = 0; i < num_frames; i++)
25
frames[i] = -1;

printf("\nReference String\tPage Frames\n");

// Loop through each reference string


for (int i = 0; i < num_references; i++) {
int page_found = 0;
int page = reference[i];

// Check if the page is already in the frame


for (int j = 0; j < num_frames; j++) {
if (frames[j] == page) {
page_found = 1;
break;
}
}
// If the page is not found in the frame, add it to the frame
if (!page_found) {
frames[frame_index] = page;
frame_index = (frame_index + 1) % num_frames;
num_page_faults++;
}
// Print the current reference string and page frames
printf("\n%4d\t\t", page);
for (int j = 0; j < num_frames; j++) {
printf("%4d", frames[j]);
}
}
printf("\n\nTotal number of page faults: %d\n", num_page_faults);
return 0;
}

OUTPUT

LEARNING OUTCOME
Thus, the FIFO replacement was executed and verified successfully.

26
EXPERIMENT 14
OBJECTIVE
To Simulate LRU page replacement algorithms

THEORY
LRU algorithm works on the principle that the least recently used page is the one that is most likely
to be replaced. This algorithm requires maintaining a record of the order in which pages are accessed.
This can be done using a linked list, a stack, or an array. Whenever a page is accessed, it is moved to
the front of the list. When a page fault occurs, the page at the end of the list is the one that is
replaced. LRU algorithm is known to perform better than FIFO and does not suffer from the Belady's
anomaly.

PROCEDURE
1. Start the program
2. Read the number of frames
3. Read the number of pages
4. Read the page numbers
5. Initialize all the elements in the frame array to -1
6. Loop through each page in the reference string:
a. Check if the current page is already in the frame array
i. If it is, update the time of the most recent access for that page
b. If it is not in the frame array, find the least recently used (LRU) page by iterating through the
frame array and finding the page with the smallest time of last access
i. Replace the LRU page with the current page
ii. Increment the number of page faults
c. Print the current reference string and the current state of the page frames
7. Print the total number of page faults
8. End the program

CODE
#include<stdio.h>
int frames_count, references_count, flag = 0, ref[50], frames[50], page_faults = 0, victim = -1;
int recent[10], lru_calculations[50], count = 0;
int get_lru_victim();
int main() {
printf("\n\t\t\t LRU PAGE REPLACEMENT ALGORITHM");
printf("\n Enter the number of frames: ");
scanf("%d", &frames_count);
printf("Enter the size of reference string: ");
scanf("%d", &references_count);
printf("Enter the reference string (separated by space): ");
for (int i = 0; i < references_count; i++)
scanf("%d", &ref[i]);
printf("\n\n\t\t LRU PAGE REPLACEMENT ALGORITHM ");
for (int i = 1; i <= frames_count; i++) {
frames[i] = -1;
lru_calculations[i] = 0;
}

27
for (int i = 0; i < 10; i++)
recent[i] = 0;
printf("\n");
printf("\nReference String\t\tPage Frames\n");
for (int i = 0; i < references_count; i++) {
flag = 0;
printf("\n\t %d\t \t \t \t ", ref[i]);
for (int j = 0; j < frames_count; j++) {
if (frames[j] == ref[i]) {
flag = 1;
break; } }
if (flag == 0) {
count++;
if (count <= frames_count)
victim++;
else
victim = get_lru_victim();
page_faults++;
frames[victim] = ref[i];
for (int j = 0; j < frames_count; j++)
printf("%4d", frames[j]); }
recent[ref[i]] = i; }
printf("\n\n\t No. of page faults: %d", page_faults);
return 0;}
int get_lru_victim() {
int temp1, temp2;
for (int i = 0; i < frames_count; i++) {
temp1 = frames[i];
lru_calculations[i] = recent[temp1]; }
temp2 = lru_calculations[0];
for (int j = 1; j < frames_count; j++) {
if (temp2 > lru_calculations[j]) {
temp2 = lru_calculations[j]; } }
for (int i = 0; i < frames_count; i++) {
if (ref[temp2] == frames[i]) {
return i; }}
return 0;}
OUTPUT

LEARNING OUTCOME
Thus, the LRU replacement was executed and verified successfully.

28
EXPERIMENT 15
OBJECTIVE
To create program for optimal page replacement algorithms.

THEORY
Optimal page replacement algorithm works on the principle of replacing the page that will not be
used for the longest period of time in the future. This algorithm requires knowing the future reference
pattern of pages, which is not feasible in practical scenarios. Therefore, this algorithm is used mainly
for theoretical analysis of other algorithms. Optimal algorithm has the lowest page fault rate among
all algorithms, but it is not implementable in practice.

PROCEDURE
1. Start the function
2. For each frame:
a. Set notfound to 1
b. For each page in the reference string starting from the current page:
i. If the page is already in the frame:
1. Set notfound to 0 and record the index of the next occurrence of the
page in the optimal calculation array (optcal)
2. Break out of the inner loop
c. If notfound is still 1:
i. Return the index of the current frame as the victim
3. Find the index of the page that will not be used for the longest period of time by finding
the maximum value in the optimal calculation array (optcal)
4. Set temp to the index of the frame with the maximum value in the optimal calculation
array
5. Find the first frame with the same page as the one in the frame with index temp and return
its index as the victim

CODE
#include <stdio.h> #include <stdlib.h>
#define MAX_FRAMES 50 #define MAX_REFERENCE_STR 50
int nof, nor, ref[MAX_REFERENCE_STR], frm[MAX_FRAMES], optcal[MAX_FRAMES],
recent[10], flag = 0, pf = 0, victim = -1, count = 0;
int optvictim(int index);
int main()
{
printf("\nOPTIMAL PAGE REPLACEMENT ALGORITHM\n");
printf("Enter the number of frames: ");
scanf("%d", &nof);
printf("Enter the reference string (separated by space): ");
scanf("%d", &nor);
printf("Enter the reference strings: ");
for (int i = 0; i < nor; i++)
scanf("%d", &ref[i]);
printf("\nOPTIMAL PAGE REPLACEMENT ALGORITHM\n");
29
printf("\nReference String\tPage Frames\n");
for (int i = 0; i < nof; i++)
{
frm[i] = -1;
optcal[i] = 0;
}
for (int i = 0; i < 10; i++) recent[i] = 0;
printf("\n");
for (int i = 0; i < nor; i++)
{
flag = 0;
printf("\n %d \t\t\t\t", ref[i]);
for (int j = 0; j < nof; j++)
{
if (frm[j] == ref[i])
{
flag = 1;
break;
}
}
if (flag == 0)
{
count++;
if (count <= nof)
victim++;
else
victim = optvictim(i);
pf++;
frm[victim] = ref[i];
for (int j = 0; j < nof; j++)
printf("%4d", frm[j]);
}
}
printf("\n\nNumber of page faults: %d\n", pf);
return 0;
}
int optvictim(int index)
{
int notfound, temp;
for (int i = 0; i < nof; i++)
{
notfound = 1;
for (int j = index; j < nor; j++)
{
if (frm[i] == ref[j])
{
notfound = 0;
optcal[i] = j;
break;
}
}

30
if (notfound == 1)
return i;
}
temp = optcal[0];
for (int i = 1; i < nof; i++)
{
if (temp < optcal[i])
temp = optcal[i];
}
for (int i = 0; i < nof; i++)
if (frm[temp] == frm[i]) return i;
return 0;
}
OUTPUT

LEARNING OUTCOME
Thus, the process optimal page replacement was executed and verified successfully

31
EXPERIMENT 16
OBJECTIVE
To Simulate Algorithm for Deadlock prevention

THEORY
PROCEDURE
1. Start the program.
2. To prevent the granting of exclusive access to a resource, attempt to avoid the mutex
condition. However, this may not be feasible for certain resources.
3. Do not engage in preemption.
4. To avoid the hold and wait condition, ensure that a process holds at most one resource at a
time. Make all resource requests at the beginning of the process. If necessary, retry the
request.
5. Address the circular wait condition by ordering all resources and ensuring that requests are
made in the correct order. This should eliminate cycles in the resource graph. Number
resources 1 through n.
6. Resources can only be requested in increasing order. A process cannot request a resource
whose number is less than any currently held resources.
7. Stop the program.

CODE
#include <stdio.h>
int max[10][10], alloc[10][10], need[10][10], avail[10], finish[10] = {0};
int p, r, i, j, flag = 0;
void fun();
int main()
{
printf("\nSIMULATION OF DEADLOCK PREVENTION\n");
printf("Enter the number of processes and resources: ");
scanf("%d %d", &p, &r);
printf("Enter the allocation matrix:\n");
for (i = 0; i < p; i++)
for (j = 0; j < r; j++)
scanf("%d", &alloc[i][j]);

printf("\nEnter the maximum matrix:\n");


for (i = 0; i < p; i++)
for (j = 0; j < r; j++)
scanf("%d", &max[i][j]);

printf("\nEnter the available matrix:\n");


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];
32
fun();
if (flag == 0)
{
for (i = 0; i < p; i++)
{
if (finish[i] != 1)
{
printf("\nFailing: Mutual exclusion\n");
for (j = 0; j < r; j++)
if (avail[j] < need[i][j])
avail[j] = need[i][j];
fun();

printf("\nBy allocating required resources to process %d, dead lock is prevented.\n", i);
printf("Lack of preemption\n");
for (j = 0; j < r; j++)
{
if (avail[j] < need[i][j])
{
avail[j] = need[i][j];
alloc[i][j] = 0;
}
}
fun();
printf("\nDead lock is prevented by allocating needed resources.\n");
printf("Failing: Hold and Wait condition\n");
for (j = 0; j < r; j++)
if (avail[j] < need[i][j])
avail[j] = need[i][j];
fun();
printf("\nAVOIDING ANY ONE OF THE CONDITION, YOU CAN PREVENT
DEADLOCK\n");
}
}
}
}

void fun(){
while (1){
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++)

33
avail[j] += alloc[i][j];
flag = 1;
finish[i] = 1;
}
}
}

if (flag == 0)
break
}
}

OUTPUT

LEARNING OUTCOME
The program for deadlock prevention was successfully executed.

34

You might also like