Operating System Lab Practicals Record
Operating System Lab Practicals Record
NAME : ………………………………..……………………........
CLASS : ……………………………………..…………….………
SEMESTER: …………..……………………………………………….
N0V-2025
GOVERNMENT THIRUMAGAL MILLS COLLEGE
(Affiliated by THIRUVALLUVAR UNIVERSITY)
GUDIYATTAM, VELLORE DISTRICT- 632602
BONAFIDE CERTIFICATE
Certified that this is the bonafied record of work done by ……………………………of the
…………..semester “BCA… .................................................................... Programming Lab” during the year
2025-2026.
Submitted for the University Practical Examination held on ………………………at the Government
Page
[Link] Date Title Signature
No.
1. Shell Programming
CPU Scheduling
[Link]
2.
[Link]
[Link]
[Link] Robin
File Allocation
4. Semaphore
d. DAG
Deadlock Detection
7.
[Link]
8.
[Link]
[Link]
AIM:
To write a program to implement shell program.
ALGORITHM:
PROGRAM:
OUTPUT
"[Link]" 10L, 133C written
[bca41@localhost ~]$ sh [Link]
Enter the Number
8
8 is Even number
2. Write a Shell program to check the given year is leap year or not
ALGORITHM:
SEPT 1: Start the program. STEP 2: Read the value of year.
STEP 3: Calculate „b=expr $y%4‟.
STEP 4: If the value of b equals 0 then print the year is a leap year
STEP 5: If the value of r not equal to 0 then print the year is not a leap year.
PROGRAM:
echo "Enter the year"
read y
b=`expr $y % 4`
if [ $b -eq 0 ] then
echo "$y is a leap year" else
echo "$y is not a leap year"
fi
OUTPUT
"[Link]" 11L, 138C written
[bca41@localhost ~]$ sh [Link]
Enter the year
2000
2000 is a leap year
ALGORITHM:
SEPT 1: Start the program.
STEP 2: Read the value of n.
STEP 3: Calculate „i=expr $n-1‟.
STEP 4: If the value of i is greater than 1 then calculate „n=expr $n \* $i‟ and „i=expr $i – 1‟
STEP 5: Print the factorial of the given number.
PROGRAM:
echo "Enter a Number"
read n
i=`expr $n - 1`
p=1
while [ $i -ge 1 ]
do
n=`expr $n \* $i`
i=`expr $i - 1`
done
echo "The Factorial of the given Number is $n"
OUTPUT
[bca41@localhost ~]$ sh [Link]
Enter a Number 5
The Factorial of the given Number is 120
ALGORITHM:
SEPT 1: Start the program.
STEP 2: Read the value of a,b.
STEP 3: Calculate the swapping of two values by using a temporary variable temp.
STEP 4: Print the value of a and b.
PROGRAM:
echo "Enter Two Numbers"
read a b
temp=$a
a=$b
b=$temp
echo "after swapping" echo $a $b
OUTPUT
"[Link]" 8L, 93C written
[bca41@localhost ~]$ sh [Link]
Enter Two Numbers
45
after swapping
RESULT:
AIM:
To write a program to implement CPU Scheduling using First come first served
DESCRIPTION:
First Come, First Serve (FCFS) is one of the simplest types of CPU scheduling algorithms. It
is exactly what it sounds like: processes are attended to in the order in which they arrive in the
ready queue, much like customers lining up at a grocery store. FCFS Scheduling is a non-
preemptive algorithm, meaning once a process starts running, it cannot be stopped until it
voluntarily relinquishes the CPU, and typically when it terminates or performs I/O. This method
schedules processes in the order they arrive, without considering priority or other factors.
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main()
{
int bt[20], wt[20], tat[20], i, n;
float wtavg, tatavg;
clrscr();
printf("\nEnter the number of processes -- ");
scanf("%d", &n);
for(i=0;i<n;i++)
{
printf("\nEnter Burst Time for Process %d -- ", i);
scanf("%d", &bt[i]);
}
wt[0] = wtavg = 0;
tat[0] = tatavg = bt[0];
for(i=1;i<n;i++)
{
wt[i] = wt[i-1] +bt[i-1];
tat[i] = tat[i-1] +bt[i];
wtavg = wtavg + wt[i];
tatavg = tatavg + tat[i];
}
printf("\t PROCESS \tBURST TIME \t WAITING TIME\t TURNAROUND TIME\n");
for(i=0;i<n;i++)
printf("\n\t P%d \t\t %d \t\t %d \t\t %d", i, bt[i], wt[i], tat[i]);
printf("\nAverage Waiting Time -- %f", wtavg/n);
printf("\nAverage Turnaround Time -- %f", tatavg/n);
getch();
}
INPUT
Enter the number of processes -- 3
Enter Burst Time for Process 0 -- 24
Enter Burst Time for Process 1 -- 3
Enter Burst Time for Process 2 -- 3
OUTPUT
PROCESS BURST TIME WAITING TIME TURNAROUND TIME
P0 24 0 24
P1 3 24 27
P2 3 27 30
RESULT:
AIM:
To write a program to implement CPU Scheduling using SJF.
DESCRIPTION
In Operating Systems, SJF stands for Shortest Job First, a CPU scheduling algorithm that
selects the process with the smallest required CPU burst time to execute next, aiming to
minimize average waiting time and maximize throughput. SJF can be preemptive (allowing a
shorter job to interrupt a longer one) or non-preemptive (a process runs to completion once it
starts).
Process Selection:
The operating system schedules the process that has the shortest execution time (burst time)
among all the processes waiting for the CPU.
Goal:
The primary goal is to minimize the overall average waiting time for processes, making it an
efficient scheduling approach.
PROGRAM:
#include<stdio.h>
#include<conio.h>
main()
{
int p[20], bt[20], wt[20], tat[20], i, k, n, temp;
float wtavg, tatavg;
clrscr();
printf("\nEnter the number of processes -- ");
scanf("%d", &n);
for(i=0;i<n;i++)
{
p[i]=i;
printf("Enter Burst Time for Process %d -- ", i);
scanf("%d", &bt[i]);
}
for(i=0;i<n;i++)
for(k=i+1;k<n;k++)
if(bt[i]>bt[k])
{
temp=bt[i];
bt[i]=bt[k];
bt[k]=temp;
temp=p[i];
p[i]=p[k];
p[k]=temp;
}
wt[0] = wtavg = 0;
tat[0] = tatavg = bt[0];
for(i=1;i<n;i++)
{
wt[i] = wt[i-1] +bt[i-1];
tat[i] = tat[i-1] +bt[i];
wtavg = wtavg + wt[i];
tatavg = tatavg + tat[i];
}
printf("\n\t PROCESS \tBURST TIME \t WAITING TIME\t TURNAROUND TIME\n");
for(i=0;i<n;i++)
printf("\n\t P%d \t\t %d \t\t %d \t\t %d", p[i], bt[i], wt[i], tat[i]);
printf("\nAverage Waiting Time -- %f", wtavg/n);
printf("\nAverage Turnaround Time -- %f", tatavg/n);
getch();
}
INPUT
Enter the number of processes -- 4
Enter Burst Time for Process 0 -- 6
Enter Burst Time for Process 1 -- 8
Enter Burst Time for Process 2 -- 7
Enter Burst Time for Process 3 -- 3
OUTPUT
PROCESS BURST TIME WAITING TIME TURNAROUND TIME
P3 3 0 3
P0 6 3 9
P2 7 9 16
P1 8 16 24
RESULT
AIM:
To write a program to implement CPU scheduling using priority.
DESCRIPTION
PROGRAM
#include<stdio.h>
#include<conio.h>
int main()
{
int p[20],bt[20],pri[20], wt[20],tat[20],i, k, n, temp;
float wtavg, tatavg;
clrscr();
printf("Enter the number of processes --- ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
p[i] = i;
printf("Enter the Burst Time & Priority of Process %d --- ",i);
scanf("%d %d",&bt[i], &pri[i]);
}
for(i=0;i<n;i++)
for(k=i+1;k<n;k++)
if(pri[i] > pri[k])
{
temp=p[i];
p[i]=p[k];
p[k]=temp;
temp=bt[i];
bt[i]=bt[k];
bt[k]=temp;
temp=pri[i];
pri[i]=pri[k];
pri[k]=temp;
}
wtavg = wt[0] = 0;
tatavg = tat[0] = bt[0];
for(i=1;i<n;i++)
{
wt[i] = wt[i-1] + bt[i-1];
tat[i] = tat[i-1] + bt[i];
wtavg = wtavg + wt[i];
tatavg = tatavg + tat[i];
}
OUTPUT
PROCESS PRIORITY BURST TIME WAITING TIME TURNAROUND TIME
1 1 1 0 1
4 2 5 1 6
0 3 10 6 16
2 4 2 16 18
3 5 1 18 19
RESULT:
AIM:
To write the program to implement CPU Scheduling using Round Robin.
DESCRIPTION
Round Robin Scheduling is a method used by operating systems to manage the execution
time of multiple processes that are competing for CPU attention. It is called "round
robin" because the system rotates through all the processes, allocating each of them a
fixed time slice or "quantum", regardless of their priority.
The primary goal of this scheduling method is to ensure that all processes are given an
equal opportunity to execute, promoting fairness among tasks.
Process Arrival: Processes enter the system and are placed in a queue.
Time Allocation: Each process is given a certain amount of CPU time, called a quantum.
Execution: The process uses the CPU for the allocated time.
Rotation: If the process completes within the time, it leaves the system. If not, it goes
back to the end of the queue.
Repeat: The CPU continues to cycle through the queue until all processes are completed.
PROGRAM
#include<stdio.h>
#include<conio.h>
int main()
{
int i,j,n,bu[10],wa[10],tat[10],t,ct[10],max;
float awt=0,att=0,temp=0;
clrscr();
printf("Enter the no of processes -- ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\nEnter Burst Time for process %d -- ", i+1);
scanf("%d",&bu[i]);
ct[i]=bu[i];
}
printf("\nEnter the size of time slice -- ");
scanf("%d",&t);
max=bu[0];
for(i=1;i<n;i++)
if(max<bu[i])
max=bu[i];
for(j=0;j<(max/t)+1;j++)
for(i=0;i<n;i++)
if(bu[i]!=0)
if(bu[i]<=t)
{
tat[i]=temp+bu[i];
temp=temp+bu[i];
bu[i]=0;
}
else
{
bu[i]=bu[i]-t;
temp=temp+t;
}
for(i=0;i<n;i++)
{
wa[i]=tat[i]-ct[i];
att+=tat[i];
awt+=wa[i];
}
printf("\nThe Average Turnaround time is -- %f",att/n);
printf("\nThe Average Waiting time is -- %f ",awt/n);
printf("\n\tPROCESS\t BURST TIME \t WAITING TIME\tTURNAROUND TIME\n");
for(i=0;i<n;i++)
printf("\t%d \t %d \t\t %d \t\t %d \n",i+1,ct[i],wa[i],tat[i]);
getch();
}
INPUT
Enter the no of processes – 3
Enter Burst Time for process 1 – 24
Enter Burst Time for process 2 -- 3
Enter Burst Time for process 3 -- 3
OUTPUT
The Average Turnaround time is – 15.666667
The Average Waiting time is -- 5.666667
RESULT:
AIM:
To write a program to implement file allocation using Sequential model.
DESCRIPTION
In this scheme, each file occupies a contiguous set of blocks on the disk. For example,
if a file requires n blocks and is given a block b as the starting location, then the blocks
assigned to the file will be: b, b+1, b+2,......b+n-1. This means that given the starting block
address and the length of the file (in terms of blocks required), we can determine the blocks
occupied by the file. The directory entry for a file with contiguous allocation contains
PROGRAM
#include <stdio.h>
#include <stdlib.h> // for exit()
int main()
{
int f[50], i, st, j, len, c;
if (c == 0)
break;
}
return 0;
}
OUTPUT
Enter the starting block & length of file: 4 10
4 -> 1
5 -> 1
6 -> 1
7 -> 1
8 -> 1
9 -> 1
10 -> 1
11 -> 1
12 -> 1
13 -> 1
The file is allocated to disk.
Do you want to enter more files? (1=Yes / 0=No) : 0
RESULT:
AIM:
To write a program to implement Indexed File Allocation
DESCRIPTION
In this scheme, a special block known as the Index block contains the pointers to all the
blocks occupied by a file. Each file has its own index block. The ith entry in the index block
contains the disk address of the ith file block.
Advantages:
This supports direct access to the blocks occupied by the file and therefore provides
fast access to the file blocks.
It overcomes the problem of external fragmentation.
Disadvantages:
The pointer overhead for indexed allocation is greater than linked allocation.
For very small files, say files that expand only 2-3 blocks, the indexed allocation would
keep one entire block (index block) for the pointers which is inefficient in terms of
memory utilization. However, in linked allocation we lose the space of only 1 pointer
per block.
PROGRAM
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{
int f[50], p, i, j, k, a, st, len, n, c;
}
printf("\nIf you want to enter one more file? (Yes=1 / No=0): ");
scanf("%d", &c);
if (c == 1)
goto X;
else
exit(0);
OUTPUT:
Enter index block: 9
Enter number of blocks needed for the file:
31
Enter the blocks for the file: 2 3
RESULT:
Thus the Program created and it is executed successfully.
EX NO: 5a
LINKED ALLOCATION
DATE:
AIM:
To write a program to implement using Linked File Allocation
DESCRIPTION
In this scheme, each file is a linked list of disk blocks which need not
be contiguous. The disk blocks can be scattered anywhere on the disk. The directory
entry contains a pointer to the starting and the ending file block. Each block contains a
pointer to the next block occupied by the file. The file 'jeep' in following image shows
how the blocks are randomly distributed. The last block (25) contains -1 indicating a null
pointer and does not point to any other block.
Advantages:
This is very flexible in terms of file size. File size can be increased easily since the
system does not have to look for a contiguous chunk of memory.
This method does not suffer from external fragmentation. This makes it
relatively better in terms of memory utilization.
Disadvantages:
Because the file blocks are distributed randomly on the disk, a large number of
seeks are needed to access every block individually. This makes linked allocation
slower.
It does not support random or direct access. We can not directly access the blocks
of a file. A block k of a file can be accessed by traversing k blocks sequentially
(sequential access ) from the starting block of the file via block pointers.
PROGRAM
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main()
{
int f[50], p, i, j, k, a, st, len, n, c;
X:
printf("\nEnter the starting index block and length of file: ");
scanf("%d%d", &st, &len);
k = len;
printf("\nIf you want to enter one more file? (Yes=1 / No=0): ");
scanf("%d", &c);
if (c == 1)
goto X;
else
exit(0);
4 -> 1
5 -> 1
6 -> 1
7 -> File is already allocated
8 -> 1
9 -> File is already allocated
10 -> 1
11 -> 1
12 -> 1
13 -> 1
14 -> 1
If you want to enter one more file? (Yes=1 / No=0):0
RESULT:
AIM:
To write a program to implement using Semaphore
DESCRIPTION
PROGRAM
#include <stdio.h>
#include <conio.h>
void main()
{
int buffer[10], bufsize, in, out, produce, consume, choice = 0;
in = 0;
out = 0;
bufsize = 10;
clrscr();
while (choice != 3)
{
printf("\n1. Produce \t 2. Consume \t 3. Exit");
printf("\nEnter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
if ((in + 1) % bufsize == out)
printf("\nBuffer is Full");
else
{
printf("\nEnter the value: ");
scanf("%d", &produce);
buffer[in] = produce;
in = (in + 1) % bufsize;
printf("\nProduced value %d", produce);
}
break;
case 2:
if (in == out)
printf("\nBuffer is Empty");
else
{
consume = buffer[out];
printf("\nConsumed value %d", consume);
out = (out + 1) % bufsize;
}
break;
case 3:
printf("\nExiting...");
break;
default:
printf("\nInvalid choice!");
break;
}
}
getch();
}
OUTPUT:
1. Produce 2. Consume 3. Exit
Enter your choice: 2
Buffer is Empty
1. Produce 2. Consume 3. Exit
Enter your choice: 1
Enter the value: 100
Produced value 100
1. Produce 2. Consume 3. Exit
Enter your choice: 2
Consumed value 100
1. Produce 2. Consume 3. Exit
Enter your choice: 3
Exiting...
RESULT:
AIM:
To write a program to implement using single-level directory.
DESCRIPTION
The single-level directory structure in file organization is the simplest way to store any
number of files in a single directory. It doesn't require creating multiple sub-directories
inside it, all the files are stored in the same directory or folder. It follows a very
straightforward approach, but the files that are being stored inside the directory must
have unique names, no two files can have the same name and reside inside the same
directory. But in the single-level directory, the user can store multiple types of files
inside a single directory, meaning that even if the extensions of the files are different
from each other or the same, they can reside inside the same directory, but only the
name must be unique. search for the number X, We start at the root. Then:
PROGRAM
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include<stdlib.h>
struct
{
char dname[10], fname[10][10];
int fcnt;
} dir;
void main()
{
int i, ch;
char f[30];
clrscr();
while (1)
{
printf("\n\n1. Create File\t2. Delete File\t3. Search File");
printf("\n4. Display Files\t5. Exit");
printf("\nEnter your choice -- ");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("\nEnter the name of the file -- ");
scanf("%s", [Link][[Link]]);
[Link]++;
break;
case 2:
printf("\nEnter the name of the file -- ");
scanf("%s", f);
for (i = 0; i < [Link]; i++)
{
if (strcmp(f, [Link][i]) == 0)
{
printf("File %s is deleted", f);
strcpy([Link][i], [Link][[Link] - 1]); // replace deleted file
[Link]--;
break;
}
}
if (i == [Link])
printf("File %s not found", f);
break;
case 3:
printf("\nEnter the name of the file -- ");
scanf("%s", f);
for (i = 0; i < [Link]; i++)
{
if (strcmp(f, [Link][i]) == 0)
{
printf("File %s is found", f);
break;
}
}
if (i == [Link])
printf("File %s not found", f);
break;
case 4:
if ([Link] == 0)
printf("\nDirectory Empty");
else
{
printf("\nThe Files are:");
for (i = 0; i < [Link]; i++)
printf("\t%s", [Link][i]);
}
break;
case 5:
exit(0);
default:
printf("\nInvalid Choice");
}
}
getch();
}
OUTPUT:
RESULT:
AIM:
To write a program to implement Two Level Directory
DESCRIPTION
PROGRAM
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
struct
{
char dname[10], fname[10][10];
int fcnt;
} dir[10];
void main()
{
int i, ch, dcnt, k;
char f[30], d[30];
clrscr();
dcnt = 0;
while (1)
{
printf("\n\n1. Create Directory\t2. Create File\t3. Delete File");
printf("\n4. Search File\t\t5. Display\t6. Exit");
printf("\nEnter your choice -- ");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("\nEnter name of directory -- ");
scanf("%s", dir[dcnt].dname);
dir[dcnt].fcnt = 0;
dcnt++;
printf("Directory created");
break;
case 2:
printf("\nEnter name of the directory -- ");
scanf("%s", d);
for (i = 0; i < dcnt; i++)
{
if (strcmp(d, dir[i].dname) == 0)
{
printf("Enter name of the file -- ");
scanf("%s", dir[i].fname[dir[i].fcnt]);
dir[i].fcnt++;
printf("File created");
break;
}
}
if (i == dcnt)
printf("Directory %s not found", d);
break;
case 3:
printf("\nEnter name of the directory -- ");
scanf("%s", d);
for (i = 0; i < dcnt; i++)
{
if (strcmp(d, dir[i].dname) == 0)
{
printf("Enter name of the file -- ");
scanf("%s", f);
for (k = 0; k < dir[i].fcnt; k++)
{
if (strcmp(f, dir[i].fname[k]) == 0)
{
printf("File %s is deleted", f);
dir[i].fcnt--;
strcpy(dir[i].fname[k], dir[i].fname[dir[i].fcnt]);
goto jmp;
}
}
printf("File %s not found", f);
goto jmp;
}
}
case 5:
if (dcnt == 0)
printf("\nNo Directories");
else
{
printf("\nDirectory\tFiles");
for (i = 0; i < dcnt; i++)
{
printf("\n%s\t\t", dir[i].dname);
for (k = 0; k < dir[i].fcnt; k++)
printf("%s\t", dir[i].fname[k]);
}
}
break;
case 6:
exit(0);
default:
printf("\nInvalid choice!");
}
}
getch();
}
OUTPUT:
Directory Files
DD FILE1
RESULT:
AIM:
To write a program to implement Hierarchical File Directory
DESCRIPTION
A hierarchical directory in an operating system is a tree-like structure for organizing files and
folders (directories). It starts with a single top-level root directory, from which other directories
(subdirectories) branch out, allowing for logical grouping and efficient management of large
numbers of files. This system uses parent-child relationships, where directories contain both files
and other directories, making it intuitive for users to find and organize their data.
Tree Structure:
Imagine a tree with the "root" at the very top, and branches (subdirectories) extending
downwards.
Parent-Child Relationship:
Each directory can contain files and other directories (its children). These subdirectories can
then contain their own files and further subdirectories, creating deeper levels of
organization.
Root Directory:
This is the topmost, base directory from which all other files and folders stem.
Directories are essentially folders that hold files, and other subdirectories.
PROGRAM
#include <stdio.h>
#include <string.h>
#include<stdlib.h> //for exit
struct
{
char dname[10], sdname[10][10], fname[10][10][10];
int sdcount, fcount[10];
}dir;
void main()
{
int i, ch, j;
char sdn[10], fn[10];
[Link] = 0;
printf("\nEnter name of root directory: ");
scanf("%s", [Link]);
while(1)
{
printf("\n\n1. Create Sub-directory");
printf("\n2. Create File");
printf("\n3. Display");
printf("\n4. Exit");
printf("\nEnter your choice: ");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("\nEnter name of sub-directory: ");
scanf("%s", [Link][[Link]]);
[Link][[Link]] = 0;
[Link]++;
break;
case 2:
printf("\nEnter name of sub-directory: ");
scanf("%s", sdn);
for(i=0; i<[Link]; i++)
{
if(strcmp(sdn, [Link][i])==0)
{
printf("Enter file name: ");
scanf("%s", [Link][i][[Link][i]]);
[Link][i]++;
break;
}
}
if(i == [Link])
printf("Sub-directory %s not found!", sdn);
break;
case 3:
printf("\nRoot directory: %s", [Link]);
for(i=0; i<[Link]; i++)
{
printf("\n Sub-directory %s", [Link][i]);
for(j=0; j<[Link][i]; j++)
printf("\n File: %s", [Link][i][j]);
}
break;
case 4: exit(0);
}
}
}
OUTPUT:
1. Create Sub-directory
2. Create File
3. Display
4. Exit
Enter your choice: 1
1. Create Sub-directory
2. Create File
3. Display
4. Exit
Enter your choice: 2
1. Create Sub-directory
2. Create File
3. Display
4. Exit
Enter your choice: 2
Root directory: dd
Sub-directory divya
File: file1
File: file2
1. Create Sub-directory
2. Create File
3. Display
4. Exit
Enter your choice: 4
RESULT:
AIM:
To write a program to implement Direct Acylic Graph.
DESCRIPTION
A DAG is a graph with directed edges and no cycles.
PROGRAM
#include <stdio.h>
#include <string.h>
#define MAX 10
struct File {
char name[20];
int used; // 1 if file exists
};
struct Directory {
char name[20];
int fileCount;
int files[MAX]; // store indices of shared files
int used; // 1 if directory exists
};
void createDir() {
char dname[20];
if (dirCount >= MAX) {
printf("\nDirectory limit reached!\n");
return;
}
printf("\nEnter directory name: ");
scanf("%s", dname);
if (findDir(dname) != -1) {
printf("Directory already exists!\n");
return;
}
strcpy(dirs[dirCount].name, dname);
dirs[dirCount].fileCount = 0;
dirs[dirCount].used = 1;
dirCount++;
printf("Directory created successfully!\n");
}
void createFile() {
char fname[20], dname[20];
int dindex, findex;
if (dindex == -1) {
printf("Directory not found!\n");
return;
}
findex = findFile(fname);
if (findex == -1) {
// create new file
if (fileCount >= MAX) {
printf("File limit reached!\n");
return;
}
strcpy(files[fileCount].name, fname);
files[fileCount].used = 1;
findex = fileCount;
fileCount++;
}
void display() {
printf("\n--- DAG Directory Structure ---\n");
for (int i = 0; i < dirCount; i++) {
if (dirs[i].used) {
printf("\nDirectory: %s\n", dirs[i].name);
for (int j = 0; j < dirs[i].fileCount; j++) {
int findex = dirs[i].files[j];
if (files[findex].used)
printf(" -> %s\n", files[findex].name);
}
}
}
}
void main() {
int choice;
clrscr(); // Turbo C only
do {
printf("\n\n--- DAG Directory Menu ---\n");
printf("1. Create Directory\n");
printf("2. Create/Link File\n");
printf("3. Display Structure\n");
printf("4. Exit\n");
printf("Enter choice: ");
scanf("%d", &choice);
switch (choice) {
case 1: createDir(); break;
case 2: createFile(); break;
case 3: display(); break;
case 4: printf("Exiting...\n"); break;
default: printf("Invalid choice!\n");
}
} while (choice != 4);
}
OUTPUT:
Enter choice: 1
Enter directory name: User2
Directory created successfully!
Enter choice: 2
Enter directory name: User1
Enter file name: [Link]
File linked/created successfully!
Enter choice: 2
Enter directory name: User2
Enter file name: [Link]
File linked/created successfully!
Enter choice: 3
--- DAG Directory Structure ---
Directory: User1
-> [Link]
Directory: User2
-> [Link]
RESULT:
AIM:
To write a program to implement Bankers Algorithm for Dead Lock Avoidance.
DESCRIPTION
The Banker’s Algorithm is a resource allocation and deadlock avoidance algorithm used in
operating systems. It ensures that a system remains in a safe state by carefully allocating
resources to processes while avoiding unsafe states that could lead to deadlocks.
The Banker's Algorithm is a smart way for computer systems to manage how programs use
resources, like memory or CPU time.
It helps prevent situations where programs get stuck and cannot finish their tasks. This
condition is known as deadlock.
By keeping track of what resources each program needs and what's available, the banker
algorithm makes sure that programs only get what they need in a safe order.
PROGRAM
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, m, i, j, k;
int alloc[10][10], max[10][10], avail[10];
int need[10][10], work[10];
int finish[10], safeSeq[10], count = 0;
// Safety algorithm
while(count < n) {
int found = 0;
for(i = 0; i < n; i++) {
if(!finish[i]) {
int flag = 1;
for(j = 0; j < m; j++) {
if(need[i][j] > work[j]) {
flag = 0;
break;
}
}
if(flag) {
for(k = 0; k < m; k++)
work[k] += alloc[i][k];
safeSeq[count++] = i;
finish[i] = 1;
found = 1;
}
}
}
if(!found) {
printf("\nSystem is NOT in a safe state!\n");
return 0;
}
}
return 0;
}
OUTPUT:
RESULT:
AIM:
To write a program to implement Dead Lock Detection
DESCRIPTION
The Deadlock detection is a process in an operating system that identifies when a situation of
circular waiting occurs, leading to a deadlock where two or more processes are stuck indefinitely
waiting for resources held by each other. Common detection methods include analyzing Wait-For
Graphs for cycles or using the Resource Allocation Graph (RAG), which visually represents
process-resource dependencies. Once a deadlock is detected, a recovery mechanism, such as
terminating a process or preempting a resource, is initiated to resolve the stalemate and restore
system functionality.
The core principle of deadlock detection is to regularly examine the system's state for the four
necessary conditions of deadlock: mutual exclusion, hold and wait, no preemption, and circular
wait. Algorithms analyze resource allocation and process requests to find a cycle, indicating a
deadlock.
A directed graph where nodes are processes, and an edge from P1 to P2 signifies that P1 is
waiting for a resource held by P2. A cycle in the WFG indicates a deadlock.
A graph with nodes representing both processes and resources, with edges showing resource
allocation or requests. A cycle in the RAG can indicate a deadlock.
PROGRAM
#include <stdio.h>
int main() {
int n, m; // n = processes, m = resources
printf("Enter number of processes: ");
scanf("%d", &n);
printf("Enter number of resources: ");
scanf("%d", &m);
int changed = 1;
while (changed) {
changed = 0;
for (int i=0; i<n; i++) {
if (!finish[i]) {
int canRun = 1;
for (int j=0; j<m; j++) {
if (request[i][j] > work[j]) {
canRun = 0;
break;
}
}
if (canRun) {
for (int j=0; j<m; j++)
work[j] += alloc[i][j];
finish[i] = 1;
changed = 1;
}
}
}
}
if (dcount == 0)
printf("\nNo Deadlock Detected. System is safe.\n");
else {
printf("\nDeadlock detected! The following processes are deadlocked:\n");
for (int i=0; i<dcount; i++)
printf("P%d ", deadlocked[i]);
printf("\n");
}
return 0;
}
OUTPUT:
RESULT:
AIM:
To write a program to implement page replacement using FIFO.
DESCRIPTION
The First-In-First-Out (FIFO) page replacement algorithm is a memory management technique
used in operating systems. It operates on the principle that the page that has been in memory the
longest is the one to be replaced when a new page needs to be loaded due to a page fault.
Here's how FIFO works:
Queue Structure:
FIFO is typically implemented using a queue data structure. When a page is loaded into memory,
it is added to the rear of the queue.
Page Fault Handling:
When a page fault occurs (meaning the required page is not in main memory), the operating
system needs to free up a page frame to load the new page.
Replacement Policy:
According to the FIFO principle, the page at the front of the queue (which represents the oldest
page in memory) is selected for replacement. This page is then removed from memory, and the
new page is loaded into the freed frame and added to the rear of the queue.
PROGRAM
#include <stdio.h>
void display(int n) {
int i;
printf("\nFrames: ");
for (i = 0; i < n; i++) {
if (fr[i] == -1)
printf(" - ");
else
printf(" %d ", fr[i]);
}
}
int main() {
int i, j, page[12] = {2,3,2,1,5,2,4,5,3,2,5,2};
int flag1, flag2, pf = 0, frsize = 3, top = 0;
// FIFO replacement
if (flag2 == 0) {
fr[top] = page[j];
top = (top + 1) % frsize;
pf++;
}
display(frsize);
}
return 0;
}
OUTPUT:
Page Reference String: 2 3 2 1 5 2 4 5 3 2 5 2
Frames: 2 - -
Frames: 2 3 -
Frames: 2 3 -
Frames: 2 3 1
Frames: 5 3 1
Frames: 5 2 1
Frames: 5 2 4
Frames: 5 2 4
Frames: 3 2 4
Frames: 3 2 4
Frames: 3 5 4
Frames: 3 5 2
RESULT:
AIM:
To write a progarm to implement optimal page replacement.
DESCRIPTION
In operating systems, whenever a new page is referred and not present in memory, page fault
occurs, and Operating System replaces one of the existing pages with newly needed page.
Different page replacement algorithms suggest different ways to decide which page to replace.
The target for all algorithms is to reduce number of page faults. In this algorithm, OS replaces
the page that will not be used for the longest period of time in future.
Optimal page replacement needs to know which pages will be used in the future, which is
not possible in real-world scenarios.
In practical systems, it is impossible to predict exactly which pages will be needed later.
It is mainly used to analyze and measure the efficiency of practical algorithms, not for actual
implementation.
Optimal Page Replacement is one of the Algorithms of Page Replacement. In this algorithm,
pages are replaced which would not be used for the longest duration of time in the future.
2. If not present, find if a page that is never referenced in future. If such a page exists, replace
this page with new page. If no such page exists, find a page that is referenced farthest in
future. Replace this page with new page.
PROGRAM
#include <stdio.h>
#include <conio.h>
int main() {
int frames[10], temp[10], pages[30];
int i, j, k, n, f, flag1, flag2, flag3, pos, max, faults = 0;
int counter = 0;
float rate;
clrscr();
// if not found
if(flag1 == 0) {
// check empty frame
for(j = 0; j < f; j++) {
if(frames[j] == -1) {
faults++;
frames[j] = pages[i];
flag2 = 1;
break;
}
}
}
// if no empty frame → apply Optimal
if(flag2 == 0) {
flag3 = 0;
for(j = 0; j < f; j++) {
temp[j] = -1;
for(k = i + 1; k < n; k++) {
if(frames[j] == pages[k]) {
temp[j] = k;
break;
}
}
}
if(flag3 == 0) {
max = temp[0];
pos = 0;
for(j = 1; j < f; j++) {
if(temp[j] > max) {
max = temp[j];
pos = j;
}
}
}
frames[pos] = pages[i];
faults++;
}
getch();
return 0;
}
OUTPUT:
Enter length of the reference string: 12
Enter the reference string:
123412514325
Enter number of frames: 3
1 -1 -1
1 2 -1
1 2 3
1 2 4
1 2 4
1 2 4
1 5 4
1 5 4
1 5 4
3 5 4
2 5 4
2 5 4
RESULT:
AIM:
To write a program to implement Shared memory and IPC
DESCRIPTION
The Least Recently Used (LRU) algorithm is a page replacement policy
employed in virtual memory management within operating systems. Its core
principle dictates that when a page fault occurs (meaning a requested page is
not found in main memory), the page to be replaced is the one that has not
been used for the longest duration.
How LRU Works:
Page Reference:
When the CPU requests a page, the system checks if it is present in the
main memory (frames).
Page Hit:
If the page is found in memory, it is considered a "page hit." In the LRU
algorithm, this page is then marked as the most recently used (e.g., by moving
it to the "top" of a conceptual stack or updating its timestamp).
Page Fault:
If the page is not found in memory, a "page fault" occurs.
The operating system retrieves the requested page from secondary
storage.
If there are empty frames in main memory, the new page is loaded into
an available frame.
If all frames are occupied, the LRU algorithm identifies the page that has
been least recently used and replaces it with the newly requested page.
PROGRAM
#include<stdio.h>
#include<conio.h>
int fr[3];
void main()
{
void display();
int p[12]={2,3,2,1,5,2,4,5,3,2,5,2},i,j,fs[3];
int index,k,l,flag1=0,flag2=0,pf=0,frsize=3;
clrscr();
for(i=0;i<3;i++)
{
fr[i]=-1;
}
for(j=0;j<12;j++)
{
flag1=0,flag2=0;
for(i=0;i<3;i++)
{
if(fr[i]==p[j])
{
flag1=1;
flag2=1; break;
}
}
if(flag1==0) {
for(i=0;i<3;i++)
{
if(fr[i]==-1)
{
fr[i]=p[j]; flag2=1;
break;
}
}
}
if(flag2==0)
{
for(i=0;i<3;i++)
fs[i]=0;
for(k=j-1,l=1;l<=frsize-1;l++,k--)
{
for(i=0;i<3;i++)
{
if(fr[i]==p[k]) fs[i]=1;
}}
for(i=0;i<3;i++)
{
if(fs[i]==0)
index=i;
}
fr[index]=p[j];
pf++;
}
display();
}
printf("\n no of page faults :%d",pf+frsize);
getch();
}
void display()
{
int i; printf("\n");
for(i=0;i<3;i++)
printf("\t%d",fr[i]);
}
OUTPUT:
2 -1 -1
2 3 -1
2 3 -1
2 3 1
2 5 1
2 5 1
2 5 4
2 5 4
3 5 4
3 5 2
3 5 2
3 5 2
no of page faults :7
RESULT:
AIM:
To write a program to implement Shared memory and IPC
DESCRIPTION
Shared Memory is an IPC mechanism where multiple processes can
access the same region of memory for reading and writing [Link] is the fastest
IPC method because processes communicate by directly reading/writing in
memory rather than using messages or files.
Purpose:
Allows efficient data exchange between processes.
Provides synchronization to prevent race conditions when multiple
processes access the shared memory concurrently.
How It Works:
A shared memory segment is created by a process (using system calls like
shmget in UNIX, or simulated in Turbo C).
Processes attach to the shared memory segment to read/write data.
After usage, processes detach from the shared memory.
Synchronization mechanisms (like semaphores) are used to prevent
simultaneous write conflicts.
Applications:
Producer-Consumer problem
Data exchange between client-server processes
Shared databases in multi-user systems
Simulating real-time systems where fast communication is required.
PROGRAM
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main()
{
clrscr();
printf("=== Simulated Shared Memory & IPC in Turbo C ===\n");
getch();
}
OUTPUT:
RESULT:
AIM:
To write a program to implement Paging Technique of memory management.
DESCRIPTION
First Paging is a memory management technique where a computer's memory is divided
into fixed-size blocks called pages (logical memory) and frames (physical
memory). Processes are loaded into memory from secondary storage not as a single
contiguous block, but as individual pages. These pages can then be placed into any available
frame, which are also fixed-size, allowing for non-contiguous allocation of memory to a
process. This strategy provides the benefits of virtual memory, avoids external
fragmentation (where memory is fragmented into small, unusable chunks), and allows for
processes to be larger than physical RAM by using the technique of swapping.
void main()
{
int ms, ps, nop, npf, p[50], frameno, offset, la, pa, i;
clrscr();
printf("=== Paging Technique Simulation ===\n");
// Memory size
printf("\nEnter the memory size (in words): ");
scanf("%d", &ms);
// Page size
printf("Enter the page size (in words): ");
scanf("%d", &ps);
// Number of pages
nop = ms / ps;
printf("The number of pages available in memory: %d\n", nop);
// Number of frames
npf = ms / ps;
printf("The number of frames available in memory: %d\n", npf);
// Logical Address
printf("\nEnter Logical Address (page number & offset): ");
scanf("%d %d", &frameno, &offset);
getch();
}
OUTPUT:
=== Paging Technique Simulation ===
RESULT:
AIM:
To write a program to implement Threading & Synchronization Applications.
DESCRIPTION
First In operating systems, a thread is the smallest unit of processing that can be
managed, allowing a single process to perform multiple tasks concurrently. Synchronization
is a mechanism to control the execution of these threads to ensure that they do not interfere
with each other when accessing shared resources, preventing problems like data
inconsistency, deadlocks, and race conditions. Synchronization is achieved using techniques
like mutexes, semaphores, and condition variables to coordinate access to critical sections of
code
PROGRAM
#include <stdio.h>
#include <conio.h>
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
int count = 0;
void main()
{
int choice;
clrscr();
printf("Producer-Consumer Problem Simulation (Turbo C)\n");
while (1)
{
printf("\n\n1. Produce Item");
printf("\n2. Consume Item");
printf("\n3. Exit");
printf("\nEnter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
producer();
break;
case 2:
consumer();
break;
case 3:
printf("\nExiting...");
getch();
return;
default:
printf("\nInvalid Choice!");
}
}
}
OUTPUT:
Producer-Consumer Problem Simulation (Turbo C)
1. Produce Item
2. Consume Item
3. Exit
Enter your choice: 1
Producer produces: 1
RESULT: