Os Lab Mannual For Students
Os Lab Mannual For Students
Name- SHRADDHA
BONAFIDE CERTIFICATE
Certified to be the bonafide record of work done by SHRADDHA Registration No. RA2311003030119 of 3rd
semester 2nd year B.TECH degree course in SRM INSTITUTE OF
SCIENCE AND TECHNOLOGY, NCR Campus of Department of Computer Science & Engineering,
in Operating System, during the academic year 2024-25.
1. Basics
i. echo SRM: to display the string SRM
ii. clear: to clear the screen
iii. date: to display the current date and time
iv. cal 2022: to display the calendar for the year 2022
v. cal 6 2022: to display the calendar for the June-2022
vi. passwd: to change password
5. I/O Redirection
Input redirection
wc –l < ex1: To find the number of lines of the file ‘ex1’
Output redirection
6. Piping
7. Environment variables
echo $HOME display the path of the home directory
echo $PS2 display the second prompt string ( > symbol by default )
Method-1
Syntax : chmod [ugo] [+/-] [ rwxa ] filename
Method-2
Syntax : chmodoctnum file1
Lab 2: Process Creation using fork() and Usage of getpid(), getppid(), wait() functions
Syntax for process creation
int fork();
Virtual fork
vfork() function is similar to fork but both processes shares the same address space.
#include <stdio.h>
#include<unistd.h>
int main()
{
int a=5,b=10,pid;
printf("Before fork a=%d b=%d \n",a,b); pid=fork();
if(pid==0)
{
a=a+1; b=b+1;
printf("In child a=%d b=%d \n",a,b);
}
else
{
sleep(1); a=a-1; b=b-1;
printf("In Parent a=%d b=%d \n",a,b);
}
return 0;
}
Output:
Program:
Calculate the number of times the text “SRMIST” is printed.
#include<stdio.h>
#include<unistd.h>
int main()
{
fork();
fork();
fork();
printf(“SRMIST\n”);
return 0;
}
Output:
How many child processes are created for the following code?
#include <stdio.h>
#include<unistd.h>
intmain()
{ fork(); fork()&&fork()||
fork();
fork();
printf(“Yes ”); return 0;
}
Output:
PROGRAM:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main( )
{
int pid;
pid=fork( );
if(pid== -1)
{
perror("fork failed");
exit(0);
}
if(pid==0)
{
printf("\nChild process is under execution"); printf("\
nProcess id of the child process is %d", getpid()); printf("\
nProcess id of the parent process is %d", getppid());
}
else
{
printf("\nParent process is under execution"); printf("\
nProcess id of the parent process is %d", getpid()); printf("\
nProcess id of the parent of parent is %d", getppid());
}
return(0);
}
Output:
Result: Program successfully executed.
Experiment-3
Program:
//Multithreading
C++ program to demonstrate multithreading using three different callables.
#include <iostream>
#include <thread>
using namespace std;
// A callable object
class thread_obj {
public:
void operator()(int x)
{
for (int i = 0; i < x; i++)
cout << "Thread using function"
" object as callable\n";
}
};
//Driver code
int main()
{
cout << "Threads 1 and 2 and 3 "
"operating independently" << endl;
return 0;
}
OUTPUT:
Program:
//USING SEMAPHORE
#include <iostream>
#include <thread>
#include <vector>
#include <random>
#include <chrono>
#include <mutex>
#include <condition_variable>
class Semaphore {
private:
mutex mtx;
condition_variable cv;
int count;
public:
Semaphore(int count_ = 0) : count(count_) {}
void acquire()
{ unique_lock<mutex>
lock(mtx);
cv.wait(lock, [this]() { return count > 0; });
--count;
}
void release()
{ unique_lock<mutex>
lock(mtx);
++count;
cv.notify_one();
}
};
// Custom semaphores
Semaphore max_capacity(4); // Restroom capacity of 4
Semaphore woman(1);
Semaphore man(1);
mutex mtx; // Mutex to protect shared resources
mutex restroomcount_mtx;
std::random_device rd;
std::mt19937 gen(rd()); // Random number generator
std::uniform_int_distribution<> dis(1, Delayx);
void Delay(void)
{
int DelayTime = dis(gen);
this_thread::sleep_for(chrono::milliseconds(DelayTime * 10)); // Simulate some delay
}
woman.acquire();
max_capacity.acquire();
{
lock_guard<mutex> lock(restroomcount_mtx);
restroom++;
cout << "Woman " << id << " has entered the Restroom" << endl;
cout << "People in the Restroom: " << restroom << endl << endl;
}
{
lock_guard<mutex> lock(mtx);
Womenwaiting--;
}
Delay();
{
lock_guard<mutex>
lock(restroomcount_mtx); restroom--;
cout << "Woman " << id << " has exited the Restroom" << endl;
cout << "People in the Restroom: " << restroom << endl << endl;
}
max_capacity.release();
man.acquire();
max_capacity.acquire();
{
lock_guard<mutex> lock(restroomcount_mtx);
restroom++;
cout << "Man " << id << " has entered the Restroom" << endl;
cout << "People in the Restroom: " << restroom << endl << endl;
}
{
lock_guard<mutex> lock(mtx);
Menwaiting--;
}
Delay();
{
lock_guard<mutex>
lock(restroomcount_mtx); restroom--;
cout << "Man " << id << " has exited the Restroom" << endl;
cout << "People in the Restroom: " << restroom << endl << endl;
}
max_capacity.release();
int main()
{
vector<thread> threads;
// Join the threads (they will stop after the set number of
visits) for (auto& t : threads)
{
t.join();
}
cout << "All threads have finished, program terminating." << endl;
return 0;
}
This generates the following output:
USING MONITOR
include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
class NinjaMonitor {
public:
//Constructor to initialize the shared resource and synchronization variables
NinjaMonitor() : SharedResource(0) {}
std::unique_lock<std::mutex> lock(mtx_);
SharedResource = new_value;
CondVar.notify_one();
}
private:
int SharedResource;
std::mutex mtx_;
std::condition_variable CondVar;
};
int main()
{ NinjaMonitor
monitor;
std::thread t(NinjaThread, std::ref(monitor));
std::this_thread::sleep_for(std::chrono::seconds(1));
monitor.UpdateSharedResource(67);
t.join();
return 0;
}
Output:
Using Semaphores :-
Here, readers have higher priority than writer. If a writer wants to write to the resource, it must wait until
there are no readers currently accessing that resource.
Here, we use :-
● one mutex m and a semaphore w.
● An integer variable read_count :- used to maintain the number of readers currently accessing
the resource. The variable read_count is initialized to 0.
● A value of 1 is given initially to m and w.
Instead of having the process to acquire lock on the shared resource, we use the mutex m to make the
process to acquire and release lock whenever it is updating the read_count variable.
a. Writer Process :
1. Writer requests the entry to the critical section.
2. If allowed i.e. wait() gives a true value, it enters and performs the write. If not allowed, it keeps
on waiting.
3. It exits the critical
section. while(TRUE)
{
wait(w);
release lock
signal(m);
acquire lock
wait(m);
read_count--;
if(read_count == 0)
signal(w);
release lock
signal(m);
}
Thus, the semaphore w is queued on both readers and writers in a manner such that preference is given
to readers if writers are also there. Thus, no reader is waiting simply because a writer has requested to
enter the critical section.
Program:
#include <iostream>
#include <thread>
#include <semaphore.h>
#include <mutex>
#include <vector>
#include <chrono>
int main() {
// Initialize the semaphore for writers (initial value 1)
sem_init(&w, 0, 1);
// Join the threads (they will stop after the set number of reads/writes)
for (auto& t : readers) {
t.join();
}
for (auto& t : writers) {
t.join();
}
cout << "\nAll readers and writers have finished their operations, program terminating" << endl;
return 0;
}
Output:
Algorithm –
monitor ForkMonitor:
integer array[0..4]
fork ← [2,2,2,2,2]
condition array[0..4]OKtoEat
operation takeForks(integer i)
if(fork[i]!=2)
waitC(OKtoEat[i])
fork[i+1]<- fork[i+1]-1
fork[i-1] <- fork[i-1]-1
operation releaseForks(integer i)
fork[i+1] <- fork[i+1]+1
fork[i-1] <- fork[i-1]
if(fork[i+1]==2)
signalC(OKtoEat[i+1])
if(fork[i-1]==2)
signalC(OKtoEat[i-1])
For each Philosopher –
loop forever :
p1 : think
p2 : takeForks(i)
p3 : eat
p4 : releaseForks(i)
Here Monitor will ensure all such needs mentioned above.
Implementation in C++ :
#define N 10
#define THINKING 2
#define HUNGRY 1
#define EATING 0
#define LEFT (phnum + 4) % N
#define RIGHT (phnum + 1) % N
Philosopher index
int phil[N];
int times = 200;
class monitor {
public:
Test for the desired condition
i.e. Left and Right philosopher are not reading
void test(int phnum)
{
if (state[(phnum + 1) % 5] != EATING
and state[(phnum + 4) % 5] != EATING
and state[phnum] == HUNGRY)
{ state[phnum] = EATING;
pthread_cond_signal(&phcond[phnum]);
}
}
pthread_mutex_lock(&condLock);
Indicates it is hungry
state[phnum] = HUNGRY;
pthread_mutex_unlock(&condLock);
}
pthread_mutex_lock(&condLock);
test(RIGHT);
test(LEFT);
pthread_mutex_unlock(&condLock);
}
constructor
monitor()
{
pthread_mutex_init(&condLock, NULL);
}
destructor
~monitor()
{
pthread_mutex_destroy(&condLock);
}
}
int main()
{
Declaration...
pthread_t thread_id[N];
pthread_attr_t attr;
Initialization...
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_JOINABLE);
Creating...
for (int i = 0; i < N; i++) {
pthread_create(&thread_id[i], &attr, philosopher,
&phil[i]);
cout << "Philosopher " << i + 1 << " is thinking..."
<< endl;
}
Joining....
for (int i = 0; i < N; i++) {
pthread_join(thread_id[i], NULL);
}
Destroying
pthread_attr_destroy(&attr);
pthread_exit(NULL);
return 0;
}
Output :
Properties -
Multiple in
stances
Each process must a priori claim maximum use
When a process requests a resource it may have to wait
When a process gets all its resources it must return them in a finite amount of time
PROGRAM-
#include<bits/stdc++.h>
using namespace std;
int allocation[10][3],need[10][3],Max[10][3],available[10][3];
int p,current[3];
bool executed[10],come;
void IMP(){
come=false;
for (int i = 0; i < 10; ++i)
{
executed[i]=false;
}
}
void Calculate(){
IMP();
int i,j;
for (i = 0; i < p; ++i)
{
for (j = 0; j < p; ++j)
{
while(executed[j] && j<p-1){
j++;
}
if (need[j][0]<=current[0]&&need[j][1]<=current[1]&&need[j][2]<=current[2])
{
if (!executed[j])
{
executed[j]=true;
current[0]+=allocation[j][0];current[1]+=allocation[j][1];current[2]+=allocation[j][2];
cout<<"\nProcess P"<<j+1;
cout<<"\nCurrent: "<<current[0]<<" "<<current[1]<<"
"<<current[2]<<"\n";
cout<<"\nProcess executed without
deadlock"; come=true;
break;
}
}
}
if (!come)
{
cout<<"\n Dead lock\n\n";
break;
}else{
come=false;
}
}
}
allocation[i][2];
}
cout<<"\n\n Table for Bankers Algo\n\n";
cout<<"Initial Resources: "<<current[0]<<" "<<current[1]<<" "<<current[2]<<"\n\n";
cout<<"Process Max Allocation Need\n";
for (int i = 0; i < p; ++i)
{
cout<<" P"<<i+1<<" ";
cout<<" "<<Max[i][0]<<" "<<Max[i][1]<<" "<<Max[i][2]<<" ";
cout<<" "<<allocation[i][0]<<" "<<allocation[i][1]<<" "<<allocation[i][2]<<" ";
cout<<" "<<need[i][0]<<" "<<need[i][1]<<" "<<need[i][2];
cout<<"\n";
}
cout<<"\n\n";
Calculate();
while(keepon){
int val,pro;
cout<<"\n\nSelect Below oprations:\n\n";
cout<<"1.Change Max of process: \n";
cout<<"2.Change Allocation of process\
n"; cout<<"3.Change Initial Resources\
n"; cout<<"4.Exit\n\n";
cin>>val;
if (val==1)
{
cout<<"\n\nEnter Process No: ";
cin>>pro;
cout<<"\nEnter New Max: ";
cin>>Max[pro-1][0]>>Max[pro-1][1]>>Max[pro-1][2];
}
else if (val==2)
{
cout<<"\n\nEnter Process No: ";
cin>>pro;
cout<<"\nEnter New Allocation: ";
cin>>allocation[pro-1][0]>>allocation[pro-1][1]>>allocation[pro-1][2];
}
else if (val==3)
{
cout<<"\nEnter Initial Resources: ";
cin>>current[0]>>current[1]>>current[2];
}
else{
break;
}
} Calculate();
return
0;
}
Output:
ALGO FCFS
1- Input the processes along with their burst time (bt).
2- Find waiting time (wt) for all processes.
3- As first process that comes need not to wait so
waiting time for process 1 will be 0 i.e. wt[0] =
0.
4- Find waiting time for all other processes i.e. for
process i ->
wt[i] = bt[i-1] + wt[i-1] .
5- Find turnaround time = waiting_time + burst_time
for all processes.
6- Find average waiting time =
total_waiting_time / no_of_processes.
7- Similarly, find average turnaround time =
total_turn_around_time /
no_of_processes.
PROGRAM:
#include<iostream>
using namespace std;
//TAT=bt[i] + wt[i]
for (int i = 0; i < n ; i++)
tat[i] = bt[i] + wt[i];
}
Driver code
int main()
{
process id's
int processes[] = { 1, 2, 3};
int n = sizeof processes / sizeof processes[0];
findavgTime(processes, n, burst_time);
return 0;
}
OUTPUT
ALGO SJF:
● Then, we will choose the process with the shortest burst time and will execute the first process.
● We will check that if both processes have the same burst time length then the FCFS
scheduling algorithm is used.
● We will make the average waiting time for the next process.
● We will begin with the first process, make the above selection, and place the other processes in a queue.
● We will calculate burst time.
● Likewise, we will run all the steps until all the processes are executed.
● PROGRAM:-
#include<stdio.h>
void main()
{
int bt[20],p[20],wt[20],tat[20],i,j,n,total=0,pos,temp;
float avg_wt,avg_tat;
printf("Enter number of process:");
scanf("%d",&n);
temp=bt[i];
bt[i]=bt[pos];
bt[pos]=temp;
temp=p[i];
p[i]=p[pos];
p[pos]=temp;
}
total+=wt[i];
}
PRIORITY SCHEDULING
Program:
#include<iostream>
using namespace std;
int main()
{
int bt[20],p[20],wt[20],tat[20],pr[20],i,j,n,total=0,pos,temp,avg_wt,avg_tat;
cout<<"Enter Total Number of Process:";
cin>>n;
cout<<"\nEnter Burst Time and Priority\n";
for(i=0;i<n;i++)
{
cout<<"\nP["<<i+1<<"]\n";
cout<<"Burst Time:";
cin>>bt[i];
cout<<"Priority:";
cin>>pr[i];
p[i]=i+1; contains process number
}
sorting burst time, priority and process number in ascending order using selection sort
for(i=0;i<n;i++)
{
pos=i;
for(j=i+1;j<n;j++)
{
if(pr[j]<pr[pos])
pos=j;
}
temp=pr[i];
pr[i]=pr[pos];
pr[pos]=temp;
temp=bt[i];
bt[i]=bt[pos];
bt[pos]=temp;
temp=p[i];
p[i]=p[pos];
p[pos]=temp;
}
wt[0]=0; //waiting time for first process is zero
calculate waiting time
for(i=1;i<n;i++)
{
wt[i]=0; for(j=0;j<i;j+
+)
wt[i]+=bt[j];
total+=wt[i];
}
avg_wt=total/n; //average waiting time
total=0;
cout<<"\nProcess\t Burst Time \tWaiting Time\tTurnaround Time";
for(i=0;i<n;i++)
{
tat[i]=bt[i]+wt[i]; //calculate turnaround time
total+=tat[i];
cout<<"\nP["<<p[i]<<"]\t\t "<<bt[i]<<"\t\t "<<wt[i]<<"\t\t\t"<<tat[i];
}
avg_tat=total/n; //average turnaround time
cout<<"\n\nAverage Waiting Time="<<avg_wt;
cout<<"\nAverage Turnaround Time="<<avg_tat;
return 0;
Result: Program successfully executed.
Experiment -10
PROGRAM
C program for FIFO page replacement algorithm
#include<stdio.h>
int main()
{
int incomingStream[] = {4, 1, 2, 4, 5};
int pageFaults = 0;
int frames = 3;
int m, n, s,
pages;
pages = sizeof(incomingStream)/sizeof(incomingStream[0]);
Program:
#include<stdio.h>
#include<limits.h>
return 0;
}
int main()
{
int n = sizeof(incomingStream)/sizeof(incomingStream[0]);
int frames = 3;
int queue[n];
int distance[n];
int occupied = 0;
int pagefault = 0;
int index;
get LRU distance for each item in frame
for (int j = 0; j < frames; j++)
{
distance[j] = 0;
traverse in reverse direction to find
at what distance frame item occurred last
for(int k = i - 1; k >= 0; k--)
{
++distance[j];
if(queue[j] == incomingStream[k])
break;
}
printf("\n");
}
OUTPUT
Page Frame1 Frame2 Frame3
1: 1
2: 1 2
3: 1 2 3
2: 1 2 3
1: 1 2 3
5: 1 2 5
2: 1 2 5
1: 1 2 5
6: 1 2 6
2: 1 2 6
5: 5 2 6
6: 5 2 6
3: 5 3 6
1: 1 3 6
3: 1 3 6
Result: Program
Page Fault: 8 successfully executed.
Experiment -12
AIM : Write a program of Best fit and Worst fit memory management policies
Driver code
int main()
{
int blockSize[] = {100, 50, 30, 120, 35};
int processSize[] = {40, 10, 30, 60};
int blocks = sizeof(blockSize)/sizeof(blockSize[0]);
int proccesses = sizeof(processSize)/sizeof(processSize[0]);
return 0 ;
OUTPUT:
Driver code
int main()
{
int blockSize[] = {100, 50, 30, 120, 35};
int processSize[] = {40, 10, 30, 60};
int blocks = sizeof(blockSize)/sizeof(blockSize[0]);
int processes = sizeof(processSize)/sizeof(processSize[0]);
return 0;
}
Output
Process Process Size Block no.
No. 40 4
1
2 10 1
3 30 2
4 60 Not Allocated
for(i=0;i<n;i++)
{
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
}
OUTPUT
It is also called as Elevator Algorithm. In this algorithm, the disk arm moves into a particular
direction till the end, satisfying all the requests coming in its path, and then it turns backend
moves in the reverse direction satisfying requests coming in its path.
It works in the way an elevator works, elevator moves in a direction completely till the last
floor of that direction and then turns back.
Example:- Given the following queue -- 95, 180, 34, 119, 11, 123, 62, 64 with the Read-write
head initially at the track 50 and the tail track being at 199. head movement is towards low
value.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int RQ[100],i,j,n,TotalHeadMoment=0,initial,size,move;
printf("Enter the number of Requests\n");
scanf("%d",&n);
printf("Enter the Requests sequence\n");
for(i=0;i<n;i++)
scanf("%d",&RQ[i]);
printf("Enter initial head position\n");
scanf("%d",&initial);
printf("Enter total disk size\n");
scanf("%d",&size);
printf("Enter the head movement direction for high 1 and for low 0\n");
scanf("%d",&move);
}
}
}
}
if movement is towards low value
else
{
for(i=index-1;i>=0;i--)
{
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
}
last movement for min size
TotalHeadMoment=TotalHeadMoment+abs(RQ[i+1]-0);
initial =0;
for(i=index;i<n;i++)
{
TotalHeadMoment=TotalHeadMoment+abs(RQ[i]-initial);
initial=RQ[i];
}
}
Output:-
Enter the number of
Request 8
Enter the Requests Sequence
95 180 34 119 11 123 62 64
Enter initial head
position 50
Enter total disk size
200
Enter the head movement direction for high 1 and for
low 0 1
Total head movement is 337
Program Output:
scanf("%d%d",
&st,&len);
for(k=st;k<(st+len);k
++) if(f[k]==0)
count++;
if(len==count)
{
for(j=st;j<(st+len);j+
+) if(f[j]==0)
{ f[j]
=1;
printf("%d\t%d\n",j,f[j]);
}
if(j!=(st+len-1))
printf("The file is allocated to disk\n");
}
else
printf("The file is not allocated \n");
printf("Do you want to enter more file(Yes - 1/No -
0)"); scanf("%d", &c);
if(c==1
) goto
x; else
exit(0);
getch();
}
Program Output:
Program-2
Debug C Programs using gdb debugger
Step 1 : Compile C program with debugging option –g
Ex.
gcc –g test.c
Step 2 : Launch gdb. You will get gdb prompt
Ex.
gdb a.out
Step 3 : Step break points inside C program
Ex.
(gdb) b 10
Break points set up at line number 10. We can have any number of break points
Step 4 : Run the program inside gdb
Ex. (gdb) r
Step 5 : Print variable to get the intermediate values of the variables at break point
Ex.
(gdb) p i
Prints the value of the variable ‘i'
Step 6 : Continue or stepping over the program using the following gdb commands
c continue till the next break
n Execute the next line. Treats function as single statement
s Similar to ‘n’ but executes function statements line by
line l List the program statements
Step 7 : Quit the debugger
(gdb) q.