Operating Systems Lab
Operating Systems Lab
PRACTICAL DETAILS
3. Write a program to
implement CPU scheduling
for first come first serve.
4. Write a program to
implement CPU scheduling
for shortest job first.
5. Write a program to
perform priority
scheduling.
6. Write a program to
implement CPU scheduling
for Round Robin.
7. Write a program for page
replacement policy using
a) LRU b) FIFO c)
Optimal
8. Write a program to
implement first fit, best fit
and worst fit algorithm for
memory management.
9. Write a program to
implement reader/writer
problem using semaphore.
10. Write a program to
implement producer-
consumer problem using
semaphores.
11. Write a program to
implement banker’s
algorithm for deadlock
avoidance.
12. Write C programs to
implement the various file
organization techniques.
PROGRAM – 1
THEORY:
PROGRAM – 2
THEORY:
PROGRAM – 3
AIM: Write a program to implement CPU scheduling for first come first serve
THEORY:
CODE:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Process {
int id;
int arrivalTime;
int burstTime;
int startTime;
int completionTime;
int turnaroundTime;
int waitingTime;
};
void nonPreemptiveFCFS(vector<Process>& processes) {
int currentTime = 0;
for (auto& process : processes) {
process.startTime = max(currentTime, process.arrivalTime);
process.completionTime = process.startTime + process.burstTime;
process.turnaroundTime = process.completionTime - process.arrivalTime;
process.waitingTime = process.turnaroundTime - process.burstTime;
currentTime = process.completionTime;
}
}
void preemptiveFCFS(vector<Process>& processes) {
int currentTime = 0;
for (auto& process : processes) {
process.startTime = max(currentTime, process.arrivalTime);
process.completionTime = process.startTime + process.burstTime;
process.turnaroundTime = process.completionTime - process.arrivalTime;
process.waitingTime = process.turnaroundTime - process.burstTime;
currentTime = process.completionTime;
}
}
void displayProcesses(const vector<Process>& processes) {
cout << "Process ID\tArrival Time\tBurst Time\tCompletion Time\tTurnaround
Time\tWaiting Time\n";
for (const auto& process : processes) {
cout << process.id << "\t\t" << process.arrivalTime << "\t\t" << process.burstTime <<
"\t\t"
<< process.completionTime << "\t\t" << process.turnaroundTime << "\t\t" <<
process.waitingTime << endl;
}
}
int main() {
int choice;
vector<Process> processes = {
{1, 0, 5, 0, 0, 0, 0},
{2, 2, 3, 0, 0, 0, 0},
{3, 4, 1, 0, 0, 0, 0},
{4, 6, 2, 0, 0, 0, 0},
{5, 8, 4, 0, 0, 0, 0}
};
cout << "Select scheduling type:\n";
cout << "1. Non-preemptive FCFS\n";
cout << "2. Preemptive FCFS\n";
cout << "Enter choice: ";
cin >> choice;
switch (choice) {
case 1:
nonPreemptiveFCFS(processes);
displayProcesses(processes);
break;
case 2:
preemptiveFCFS(processes);
displayProcesses(processes);
break;
default:
cout << "Invalid choice.\n";
break;
}
return 0;
}
OUTPUT:
PROGRAM – 4
AIM: Write a program to implement CPU scheduling for shortest job first
THEORY:
CODE:
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <climits> // Include the necessary
header using namespace std;
struct Process {
int id;
int arrivalTime;
int burstTime;
int startTime;
int completionTime;
int turnaroundTime;
int waitingTime;
int remainingTime; // For preemptive SJF
};
void nonPreemptiveSJF(vector<Process>& processes) {
sort(processes.begin(), processes.end(), [](const Process& a, const Process& b) {
return a.burstTime < b.burstTime || (a.burstTime == b.burstTime && a.arrivalTime <
b.arrivalTime);
});
int currentTime = 0;
for (auto& process : processes) {
process.startTime = max(currentTime, process.arrivalTime);
process.completionTime = process.startTime + process.burstTime;
process.turnaroundTime = process.completionTime - process.arrivalTime;
process.waitingTime = process.turnaroundTime - process.burstTime;
currentTime = process.completionTime;
}
}
void preemptiveSJF(vector<Process>& processes) {
sort(processes.begin(), processes.end(), [](const Process& a, const Process& b) {
return a.arrivalTime < b.arrivalTime;
});
int currentTime = 0;
int completed = 0;
vector<bool> executed(processes.size(), false);
while (completed < processes.size()) {
int shortest = -1;
int shortestBurst = INT_MAX;
for (int i = 0; i < processes.size(); ++i) {
if (processes[i].arrivalTime <= currentTime && !executed[i]
&& processes[i].burstTime < shortestBurst) {
shortest = i;
shortestBurst = processes[i].burstTime;
}
}
if (shortest == -1) {
currentTime++;
continue;
}
processes[shortest].startTime =
currentTime;
processes[shortest].burstTime--;
currentTime++;
if (processes[shortest].burstTime == 0) {
processes[shortest].completionTime = currentTime;
processes[shortest].turnaroundTime = processes[shortest].completionTime -
processes[shortest].arrivalTime;
processes[shortest].waitingTime = processes[shortest].turnaroundTime -
processes[shortest].remainingTime;
executed[shortest] = true;
completed++;
}
}
}
void displayProcesses(const vector<Process>& processes) {
cout << "Process ID\tArrival Time\tBurst Time\tCompletion Time\tTurnaround
Time\tWaiting Time\n";
for (const auto& process : processes) {
cout << process.id << "\t\t" << process.arrivalTime << "\t\t" << process.remainingTime
<< "\t\t"
<< process.completionTime << "\t\t" << process.turnaroundTime << "\t\t" <<
process.waitingTime << endl;
}
}
int main() {
int choice;
vector<Process> processes = {
{1, 0, 8, 0, 0, 0, 0, 8},
{2, 1, 4, 0, 0, 0, 0, 4},
{3, 2, 9, 0, 0, 0, 0, 9},
{4, 3, 5, 0, 0, 0, 0, 5},
{5, 4, 2, 0, 0, 0, 0, 2}
};
cout << "Select scheduling type:\n";
cout << "1. Non-preemptive SJF\n";
cout << "2. Preemptive SJF\n";
cout << "Enter choice:
"; cin >> choice;
switch (choice) {
case 1:
nonPreemptiveSJF(processes);
displayProcesses(processes);
break;
case 2:
preemptiveSJF(processes);
displayProcesses(processes);
break;
default:
cout << "Invalid choice.\n";
break;
}
return 0;
}
OUTPUT:
PROGRAM – 5
THEORY:
CODE:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
struct Process {
int id;
int arrivalTime;
int burstTime;
int priority;
int startTime;
int completionTime;
int turnaroundTime;
int waitingTime;
int remainingTime; // For preemptive Priority
};
int currentTime = 0;
for (auto& process : processes) {
process.startTime = max(currentTime, process.arrivalTime);
process.completionTime = process.startTime + process.burstTime;
process.turnaroundTime = process.completionTime - process.arrivalTime;
process.waitingTime = process.turnaroundTime - process.burstTime;
currentTime = process.completionTime;
}
}
int currentTime = 0;
int completed = 0;
vector<bool> executed(processes.size(), false);
while (completed < processes.size()) {
int highestPriority = INT_MAX;
int highestPriorityIdx = -1;
if (highestPriorityIdx == -1) {
currentTime++;
continue;
}
processes[highestPriorityIdx].startTime =
currentTime;
processes[highestPriorityIdx].remainingTime--;
currentTime++;
if (processes[highestPriorityIdx].remainingTime == 0) {
processes[highestPriorityIdx].completionTime = currentTime;
processes[highestPriorityIdx].turnaroundTime =
processes[highestPriorityIdx].completionTime - processes[highestPriorityIdx].arrivalTime;
processes[highestPriorityIdx].waitingTime =
processes[highestPriorityIdx].turnaroundTime - processes[highestPriorityIdx].burstTime;
executed[highestPriorityIdx] = true;
completed++;
}
}
}
int main() {
int choice;
vector<Process> processes = {
{1, 0, 8, 3, 0, 0, 0, 0, 8},
{2, 1, 4, 1, 0, 0, 0, 0, 4},
{3, 2, 9, 2, 0, 0, 0, 0, 9},
{4, 3, 5, 4, 0, 0, 0, 0, 5},
{5, 4, 2, 5, 0, 0, 0, 0, 2}
};
switch (choice) {
case 1:
nonPreemptivePriority(processes);
displayProcesses(processes);
break;
case 2:
preemptivePriority(processes);
displayProcesses(processes);
break;
default:
cout << "Invalid choice.\n";
break;
}
return 0;
}
OUTPUT:
PROGRAM – 6
THEORY:
CODE:
#include<iostream>
using namespace std;
// Function to find the waiting time for all
// processes
void findWaitingTime(int processes[], int n,
int bt[], int wt[], int quantum)
{
// Make a copy of burst times bt[] to store remaining
// burst times.
int rem_bt[n];
for (int i = 0 ; i < n ; i++)
rem_bt[i] = bt[i];
// Driver code
int main()
{
// process id's
int processes[] = { 1, 2, 3};
int n = sizeof processes / sizeof processes[0];
// Time quantum
int quantum = 2;
findavgTime(processes, n, burst_time, quantum);
return 0;
}
OUTPUT:
PROGRAM – 7 (a)
THEORY:
CODE:
#include<bits/stdc++.h>
using namespace std;
{
// To represent set of current pages. We use
// an unordered_set so that we quickly check
// if a page is present in set or not
unordered_set<int> s;
// To store least recently used indexes
// of pages.
unordered_map<int, int> indexes;
// Start from initial page
int page_faults = 0;
for (int i=0; i<n; i++) {
// Check if the set can hold more
pages if (s.size() < capacity) {
// Insert it into set if not present
// already which represents page
fault if (s.find(pages[i])==s.end())
{
s.insert(pages[i]);
else{
// Check if current page is not already
// present in the set
if (s.find(pages[i]) == s.end()) {
// Find the least recently used pages
// that is present in the set
int lru = INT_MAX, val;
for (auto it=s.begin(); it!=s.end(); it++) {
if (indexes[*it] < lru) {
lru = indexes[*it];
val = *it;
}
}
return page_faults;
}
// Driver code
int main()
{
int pages[] = {7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2};
int n = sizeof(pages)/sizeof(pages[0]);
int capacity = 4;
cout << pageFaults(pages, n, capacity);
return 0;
}
OUTPUT:
PROGRAM – 7 (b)
THEORY:
CODE:
return page_faults;
}
// Driver code
int main()
{
int pages[] = {7, 0, 1, 2, 0, 3, 0, 4,
2, 3, 0, 3, 2};
int n = sizeof(pages)/sizeof(pages[0]);
int capacity = 4;
cout << pageFaults(pages, n, capacity);
return 0;
}
OUTPUT:
PROGRAM – 7 (c)
AIM: Write a program for page replacement policy using Optimal Approach
THEORY:
CODE:
// Driver Function
int main()
{
int pg[] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2 };
int pn = sizeof(pg) / sizeof(pg[0]);
int fn = 4;
optimalPage(pg, pn, fn);
return 0;
}
OUTPUT:
PROGRAM – 8
AIM: Write a program to implement first fit, best fit and worst fit algorithm for
memory management
THEORY:
(A) FIRST FIT
CODE:
break;
}
}
}
// Driver code
int main()
{
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426};
int m = sizeof(blockSize) / sizeof(blockSize[0]);
int n = sizeof(processSize) /
sizeof(processSize[0]);
return 0 ;
}
OUTPUT:
(B) BEST FIT
CODE:
// Driver Method
int main()
{
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426};
int m = sizeof(blockSize) / sizeof(blockSize[0]);
int n = sizeof(processSize) /
sizeof(processSize[0]);
return 0 ;
}
OUTPUT:
(C) WORST FIT
CODE:
// Driver code
int main()
{
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426};
int m = sizeof(blockSize)/sizeof(blockSize[0]);
int n = sizeof(processSize)/sizeof(processSize[0]);
return 0 ;
}
OUTPUT:
PROGRAM – 9
THEORY:
CODE:
#include<semaphore.h>
#include<stdio.h>
#include<pthread.h>
# include<bits/stdc++.h>
using namespace std;
void *reader(void *);
void *writer(void *);
int readcount=0,writecount=0,sh_var=5,bsize[5];
sem_t x,y,z,rsem,wsem;
pthread_t r[3],w[2];
void *reader(void *i){
cout << "\n------------------------";
cout << "\n\n reader-" << i << " is reading";
sem_wait(&z);
sem_wait(&rsem);
sem_wait(&x);
readcount++;
if(readcount==1)
sem_wait(&wsem);
sem_post(&x);
sem_post(&rsem);
sem_post(&z);
cout << "\nupdated value :" << sh_var;
sem_wait(&x);
readcount--;
if(readcount==0)
sem_post(&wsem);
sem_post(&x);
}
sh_var=sh_var+5;
sem_post(&wsem);
sem_wait(&y);
writecount--;
if(writecount==0)
sem_post(&rsem);
sem_post(&y);
}
int main(){
sem_init(&x,0,1);
sem_init(&wsem,0,1);
sem_init(&y,0,1);
sem_init(&z,0,1);
sem_init(&rsem,0,1);
pthread_create(&r[0],NULL,(void *)reader,(void *)0);
pthread_create(&w[0],NULL,(void *)writer,(void
*)0); pthread_create(&r[1],NULL,(void *)reader,(void
*)1); pthread_create(&r[2],NULL,(void *)reader,(void
*)2); pthread_create(&r[3],NULL,(void *)reader,(void
*)3); pthread_create(&w[1],NULL,(void *)writer,
(void *)3); pthread_create(&r[4],NULL,(void *)reader,
(void *)4); pthread_join(r[0],NULL);
pthread_join(w[0],NULL);
pthread_join(r[1],NULL);
pthread_join(r[2],NULL);
pthread_join(r[3],NULL);
pthread_join(w[1],NULL);
pthread_join(r[4],NULL);
return(0);
}
OUTPUT:
PROGRAM – 10
THEORY:
CODE:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
// Function prototypes
void producer(int id);
void consumer(int
id);
int main() {
// Create producer and consumer threads
std::thread producerThread(producer, 1);
std::thread consumerThread(consumer, 1);
return 0;
}
// Producer function
void producer(int id) {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();
// Simulate some work being done by the producer
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
// Consumer function
void consumer(int id) {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();
OUTPUT:
PROGRAM – 11
THEORY:
CODE:
// Banker's Algorithm
#include <iostream>
using namespace std;
int main()
{
// P0, P1, P2, P3, P4 are the Process names here
int n, m, i, j, k;
n = 5; // Number of processes
m = 3; // Number of resources
int alloc[5][3] = { { 0, 1, 0 }, // P0 // Allocation Matrix
{ 2, 0, 0 }, // P1
{ 3, 0, 2 }, // P2
{ 2, 1, 1 }, // P3
{ 0, 0, 2 } }; // P4
int flag = 0;
for (j = 0; j < m; j++) {
if (need[i][j] > avail[j]){
flag = 1;
break;
}
}
if (flag == 0) {
ans[ind++] = i;
for (y = 0; y < m; y++)
avail[y] += alloc[i][y];
f[i] = 1;
}
}
}
}
int flag = 1;
if(flag==1)
{
cout << "Following is the SAFE Sequence" <<
endl; for (i = 0; i < n - 1; i++)
cout << " P" << ans[i] << " ->";
cout << " P" << ans[n - 1] <<endl;
}
return (0);
}
OUTPUT:
PROGRAM – 12
THEORY:
(A) SINGLE LEVEL DIRECTORY
ORGANIZATION CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_FILES 100
#define MAX_FILENAME 20
struct File {
char filename[MAX_FILENAME];
// You can add more attributes to the file structure if needed
};
struct Directory {
struct File files[MAX_FILES];
int numFiles;
};
void initializeDirectory(struct Directory *dir)
{ dir->numFiles = 0;
}
void addFile(struct Directory *dir, const char *filename)
{ if (dir->numFiles < MAX_FILES) {
strncpy(dir->files[dir->numFiles].filename, filename, MAX_FILENAME - 1);
dir->files[dir->numFiles].filename[MAX_FILENAME - 1] = '\0';
dir->numFiles++;
printf("File '%s' added successfully.\n", filename);
} else {
printf("Directory is full. Cannot add file '%s'.\n", filename);
}
}
void listFiles(struct Directory *dir) {
printf("Files in the directory:\n");
for (int i = 0; i < dir->numFiles; i++) {
printf("%s\n", dir->files[i].filename);
}
}
int main() {
struct Directory myDirectory;
initializeDirectory(&myDirectory);
int choice;
char filename[MAX_FILENAME];
do {
printf("\n1. Add File\n");
printf("2. List Files\n");
printf("3. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the filename: ");
scanf("%s", filename);
addFile(&myDirectory, filename);
break;
case 2:
listFiles(&myDirectory);
break;
case 3:
printf("Exiting the program.\n");
break;
default:
printf("Invalid choice. Please enter a valid option.\n");
}
return 0;
}
OUTPUT:
(B) TWO LEVEL DIRECTORY ORGANIZATION
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_FILES 100
#define MAX_FILENAME 20
#define MAX_SUBDIRECTORIES 10
#define MAX_SUBDIR_NAME 20
struct File {
char filename[MAX_FILENAME];
// You can add more attributes to the file structure if needed
};
struct Directory {
char dirname[MAX_SUBDIR_NAME];
struct File files[MAX_FILES];
int numFiles;
};
struct TwoLevelFileSystem {
struct Directory directories[MAX_SUBDIRECTORIES];
int numDirectories;
};
void initializeFileSystem(struct TwoLevelFileSystem *fs) {
fs->numDirectories = 0;
}
void initializeDirectory(struct Directory *dir, const char *dirname)
{ strncpy(dir->dirname, dirname, MAX_SUBDIR_NAME - 1);
dir->dirname[MAX_SUBDIR_NAME - 1] = '\0';
dir->numFiles = 0;
}
void addFile(struct Directory *dir, const char *filename)
{ if (dir->numFiles < MAX_FILES) {
strncpy(dir->files[dir->numFiles].filename, filename, MAX_FILENAME - 1);
dir->files[dir->numFiles].filename[MAX_FILENAME - 1] = '\0';
dir->numFiles++;
printf("File '%s' added to directory '%s'.\n", filename, dir->dirname);
} else {
printf("Directory is full. Cannot add file '%s' to directory '%s'.\n", filename, dir-
>dirname);
}
}
void listFiles(struct Directory *dir) {
printf("Files in directory '%s':\n", dir->dirname);
for (int i = 0; i < dir->numFiles; i++) {
printf("%s\n", dir->files[i].filename);
}
}
int main() {
struct TwoLevelFileSystem myFileSystem;
initializeFileSystem(&myFileSystem);
int choice;
char dirname[MAX_SUBDIR_NAME];
char filename[MAX_FILENAME];
do {
printf("\n1. Create Directory\n");
printf("2. Add File to Directory\n");
printf("3. List Files in Directory\n");
printf("4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the directory name: ");
scanf("%s", dirname);
initializeDirectory(&myFileSystem.directories[myFileSystem.numDirectories],
dirname);
myFileSystem.numDirectories++;
printf("Directory '%s' created successfully.\n", dirname);
break;
case 2:
printf("Enter the directory name: ");
scanf("%s", dirname);
int found = 0;
for (int i = 0; i < myFileSystem.numDirectories; i++) {
if (strcmp(myFileSystem.directories[i].dirname, dirname) == 0) {
found = 1;
printf("Enter the filename: ");
scanf("%s", filename);
addFile(&myFileSystem.directories[i], filename);
break;
}
}
if (!found) {
printf("Directory '%s' not found.\n", dirname);
}
break;
case 3:
printf("Enter the directory name: ");
scanf("%s", dirname);
found = 0;
for (int i = 0; i < myFileSystem.numDirectories; i++) {
if (strcmp(myFileSystem.directories[i].dirname, dirname) == 0) {
found = 1;
listFiles(&myFileSystem.directories[i]);
break;
}
}
if (!found) {
printf("Directory '%s' not found.\n", dirname);
}
break;
case 4:
printf("Exiting the program.\n");
break;
default:
printf("Invalid choice. Please enter a valid option.\n");
}
return 0;
}
OUTPUT:
(C) HIERARCHIAL DIRECTORY ORGANIZATION
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct File {
char filename[MAX_FILENAME];
// You can add more attributes to the file structure if needed
};
struct Directory {
char dirname[MAX_SUBDIR_NAME];
struct File files[MAX_FILES];
int numFiles;
struct Directory *subdirectories[MAX_SUBDIRECTORIES];
int numSubdirectories;
};
struct HierarchicalFileSystem {
struct Directory root;
};
printf("Files:\n");
for (int i = 0; i < dir->numFiles; i++) {
printf("%s\n", dir->files[i].filename);
}
printf("Subdirectories:\n");
for (int i = 0; i < dir->numSubdirectories; i++) {
printf("%s\n", dir->subdirectories[i]->dirname);
}
}
int main() {
struct HierarchicalFileSystem myFileSystem;
initializeFileSystem(&myFileSystem);
addFile(&myFileSystem.root, "RootFile1");
addSubdirectory(&myFileSystem.root, &subDir1);
addFile(&subDir1, "File1");
addFile(&subDir1, "File2");
addSubdirectory(&myFileSystem.root, &subDir2);
addFile(&subDir2, "File3");
int choice;
do {
printf("\n1. List Files and Subdirectories\n");
printf("2. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
listFilesAndSubdirectories(&myFileSystem.root);
break;
case 2:
printf("Exiting the program.\n");
break;
default:
printf("Invalid choice. Please enter a valid option.\n");
}
return 0;
}
OUTPUT: