Professional Documents
Culture Documents
OS_lab_manual_PPP
OS_lab_manual_PPP
Year: 2021-2022
Experiment List
Expt
Title
No. Nature of Experiment
COMMANDS:
1. To create a file.
Syntax: $ cat>filename
Example: $ cat>ex1
8. To delete a file
Syntax: $ rm filename
Example: $ rm ex1
13. Echo
i. To display the filename starting with single letter
Syntax: $ echo?
15. Head
i. To display first 10 lines
Syntax: $ head filename
COMMANDS:
1. Calendar:
i. To display the calendar.
Syntax: $ cal
2. Date:
i. To display system date.
Syntax: $ date
Output: Tue Jan 20 10:54:25 IST 2009
3. WHO
i. To display the login details
Syntax: $ who
Output: root :0 Jan 20 10:51
cs1010 pts/0 Jan 20 10:51 (172.16.1.72)
4. MAN
i. It is used to view more details of all the commands
Syntax: $ man command_name
Example: $ man date
Experiment No. : 3
Shell Scripting
- Shell Scripting is an open-source computer program designed to be run by the
Unix/Linux shell. Shell Scripting is a program to write a series of commands for the
shell to execute. It can combine lengthy and repetitive sequences of commands into
a single and simple script that can be stored and executed anytime which, reduces
programming efforts.
What is Shell?
- Shell is a UNIX term for an interface between a user and an operating system
service. Shell provides users with an interface and accepts human-readable
commands into the system and executes those commands which can run
automatically and give the program’s output in a shell script.
- An Operating is made of many components, but its two prime components are –
i. Kernel
ii. Shell
A shell in a Linux operating system takes input from you in the form of commands,
processes it, and then gives an output. It is the interface through which a user works
on the programs, commands, and scripts. A shell is accessed by a terminal which
runs it.
Bourne shell was the first shell to appear on Unix systems, thus it is referred to as
"the shell". Bourne shell is usually installed as /bin/sh on most versions of Unix. For
this reason, it is the shell of choice for writing scripts that can be used on different
versions of Unix.
chmod:
To change directory permissions in Linux, use the following:
chmod +rwx filename to add permissions.
chmod -rwx directoryname to remove permissions.
chmod +x filename to allow executable permissions.
chmod -wx filename to take out write and executable permissions.
“r” is for read, “w” is for write, and “x” is for execute.
Shell scripting
cat /etc/shells
- This command gives shell types that are supported by your system.
which bash
- This command is used to know where bash is located.
-
Variables
There are two types of variables:
i. System variables
- Ex.
echo $BASH
echo $BASH_VERSION
echo $PWD
IF statement
Syntax:
if [condition]
then
statements
fi
Ex.
Count=10
if [ $Count > 9 ]
then
echo “Condition is true”
else
echo “Condition is false
fi
Case statement
Syntax:
case expression in
pattern1)
statement;;
pattern2)
statement;;
...
*)
Statement;;
esac
Ex.
vehicle= $1
case $vehicle in
“car” )
echo “Rent of $vehicle is 100 dollar” ;;
“van” )
echo “Rent of $vehicle is 80 dollar” ;;
“bicycle” )
echo “Rent of $vehicle is 5 dollar” ;;
“truck” )
echo “Rent of $vehicle is 150 dollar” ;;
*)
Echo “unknown vehicle” ;;
esac
While loops
Syntax:
while [condition]
do
command 1
command 2
command 3
done
Ex.
n=1
while (( $n <= 10 ))
do
echo “$n”
(( ++n ))
done
Experiment No. 4
Title: Shell script programming using the commands grep, awk and sed
1. grep command
- grep means Global Regular Expression Print
- grep command process text line by line and print any line which matches
specified pattern.
- It searches some kind of pattern, word or sentence in a text file or number of text
file.
viii. –c
- It gives number of lines that matches the pattern.
e.g grep –c “directory” file.txt
ix. -v
- It prints out all the lines that do not matches the pattern
e.g grep –v “directory” file.txt
x. –A
- It prints the searched line and n lines after the result.
e.g grep –A 2 “directory” file.txt
xi. –B
- It prints the searched line and n lines before the result.
e.g grep –B 2 “directory” file.txt
xii. –C
- It prints the searched line and n lines after and before the result.
e.g grep -C 2 “directory” file.txt
2. AWK
- It is used for text processing and formatting.
- Awk is a scripting language used for manipulating data and generating reports.
- The awk command programming language requires no compiling and allows the
user to use variables, numeric functions, string functions, and logical operators.
- AWK Operations:
(a) Scans a file line by line
(b) Splits each input line into fields
(c) Compares input line/fields to pattern
(d) Performs action(s) on matched lines
- Syntax:
awk options 'selection _criteria {action }' input-file > output-file
NF
NF command keeps a count of the number of fields within the current
input record.
Ex. awk '{print $4, NF}' dept.txt
OFS:
- OFS command stores the output field separator, which separates the
fields when Awk prints them. The default is a blank space. Whenever
print has several parameters separated with commas, it will print the
value of OFS in between each parameter.
Ex. awk {OFS= “==”}{print $1, $2}’ dept.txt
ORS:
- ORS command stores the output record separator, which separates the
output lines when Awk prints them. The default is a newline character.
print automatically outputs the contents of ORS at the end of whatever it
is given to print.
Ex. awk {ORS= “:”}{print $1, $2}’ dept.txt
3. SED
- SED command is stands for stream editor and it can perform lots of function on
file like, searching, find and replace insertion or deletion.
- Though most common use of SED command is for substitution or for find and
replace.
- By using SED you can edit files even without opening it, which is much quicker
way to find and replace something in file, than first opening that file in VI Editor
and then changing it.
- SED is a powerful text stream editor. Can do insertion, deletion, search and
replace(substitution).
- SED command in unix supports regular expression which allows it perform
complex pattern matching.
- Syntax:
The FCFS algorithm is thus practically troublesome for time sharing systems,
where it is important that each user get a share of the CPU at regular intervals.
It would be disastrous to allow one process to keep the CPU for an extended
period.
For FCFS scheduling algorithm, read the number of processes/jobs in the system,
their CPU burst times. The scheduling is performed on the basis of arrival time of
the processes irrespective of their other parameters. Each process will be
executed according to its arrival time. Calculate the waiting time and turnaround
time of each of the processes accordingly.
This algorithm associates with each process the length of the process's next CPU
burst.
When the CPU is available, it is assigned to the process that has the smallest next
CPU burst.
If the next CPU bursts of two processes are the same, FCFS scheduling is used to
break the tie.
More appropriate term for this scheduling method would be the shortest-next-
CPU-burst algorithm, because scheduling depends on the length of the next CPU
burst of a process, rather than its total length.
o For SJF scheduling algorithm, read the number of processes/jobs in the system,
their CPU burst times. Arrange all the jobs in order with respect to their burst
times. There may be two jobs in queue with the same execution time, and then
FCFS approach is to be performed. Each process will be executed according to
the length of its burst time. Then calculate the waiting time and turnaround time
of each of the processes accordingly.
Priority Scheduling Algorithm
Priority is associated with each process and CPU is allocated to the process which
has highest priority.
Equal priority processes are scheduled in FCFS order.
SJF algorithm is simply a priority algorithm where priority is inverse of the next
(predicated) CPU burst.
Priority scheduling is either preemptive or non-preemptive.
Preemptive priority scheduling will preempt the CPU if priority of newly arrived
process is higher than the priority of currently running process.
A non-preemptive priority scheduling algorithm will simply put new process at
the head of ready queue.
Experiment No. : 6
The producer tries to insert data into an empty slot of the buffer.
The consumer tries to remove data from a filled slot in the buffer.
The producer must not insert data when the buffer is full.
The consumer must not remove data when buffer is empty.
The producer and consumer should not insert and remove data simultaneously.
Solution to the Bounded Buffer Problem using Semaphores:
1. m(mutex)
2. empty
- It is counting semaphore whose initial value is the number of slots in the buffer, since
initially all slots are empty.
3. full
Safety Algorithm
1) Let Work and Finish be vectors of length m and n, respectively. Initialize:
Work= Available
Finish[i] =false; for i = 0, 1, 2,... , n - 1.
2) Find an index i such that both
a. Finish[i] =false
b. Needi <= Work
If no such i exists, go to step 4.
3) Work = Work + Allocation[i]
Finish[i] = true
Go to step 2.
4) If Finish[i] = true for all i, then the system is in a safe state.
Experiment No. 8
Title: Implementation of synchronization primitives-semaphores, locks and
conditional variables.
Theory:
1. Synchronization primitive: semaphore
The basic code cannot be written directly, as the functions require to be atomic and
writing code directly would lead to a context switch without function completion
and would result in a mess.
The POSIX system in Linux presents its own built-in semaphore library. To use it,
we have to :
1. Include semaphore.h
Where,
If the value of pshared is zero, then the semaphore cannot be shared between
processes. If the value of pshared is nonzero, then the semaphore can be shared
between processes.
A semaphore must not be reinitialized while other threads might be using the
semaphore.
Code:
// C program to demonstrate working of Semaphores
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
Sem_t mutex;
//critical section
sleep(4);
//signal
printf("\nJust Exiting...\n");
sem_post(&mutex);
}
int main()
{
sem_init(&mutex, 0, 1);
pthread_t t1,t2;
pthread_create(&t1,NULL,thread,NULL);
sleep(2);
pthread_create(&t2,NULL,thread,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
sem_destroy(&mutex);
return 0;
}
Output:
pallavi@ubuntu:~$ cd Desktop
pallavi@ubuntu:~/Desktop$ cd OS
pallavi@ubuntu:~/Desktop/OS$ gcc -o synchro synchro.c -pthread
pallavi@ubuntu:~/Desktop/OS$ ./synchro
Entered..
Just Exiting...
Entered..
Just Exiting...
Suppose one thread has locked a region of code using mutex and is executing that
piece of code.
Now if scheduler decides to do a context switch, then all the other threads which are
ready to execute the same region are unblocked.
Only one of all the threads would make it to the execution but if this thread tries to
execute the same region of code that is already locked then it will again go to sleep.
Context switch will take place again and again but no thread would be able to
execute the locked region of code until the mutex lock over it is released.
Mutex lock will only be released by the thread who locked it.
So this ensures that once a thread has locked a piece of code then no other thread
can execute the same region until it is unlocked by the thread that locked it.
A mutex is initialized and then a lock is achieved by calling the following two functions
:
The first function initializes a mutex and through second function any critical region in the
code can be locked.
Returned value
The mutex can be unlocked and destroyed by calling following two functions :
The first function releases the lock and the second function destroys the lock so that it
cannot be used anywhere in future.
1. int pthread_mutex_unlock(pthread_mutex_t *mutex) : Releases a mutex object. If
one or more threads are waiting to lock the mutex, pthread_mutex_unlock() causes one of
those threads to return from pthread_mutex_lock() with the mutex object acquired. If no
threads are waiting for the mutex, the mutex unlocks with no current owner. When the
mutex has the attribute of recursive the use of the lock may be different. When this kind of
mutex is locked multiple times by the same thread, then unlock will decrement the count
and no waiting thread is posted to continue running with the lock. If the count is
decremented to zero, then the mutex is released and if any thread is waiting for it is posted.
Returned value
Returned value
Code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
pthread_t tid[3];
int counter;
pthread_mutex_t lock;
pthread_mutex_lock(&lock);
unsigned long i = 0;
counter += 1;
pthread_mutex_unlock(&lock);
return NULL;
int main(void)
int i = 0;
int error;
if (pthread_mutex_init(&lock, NULL) != 0) {
return 1;
while (i < 3) {
error = pthread_create(&(tid[i]),
NULL,
&trythis, NULL);
if (error != 0)
strerror(error));
i++;
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_join(tid[2], NULL);
pthread_mutex_destroy(&lock);
return 0;
Output:
pallavi@ubuntu:~/Desktop/OS$ ./exp8.2
Syntax of pthread_cond_wait() :
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict
mutex);
where,
- Return Value :
On success, 0 is returned ; otherwise, an error
Syntax of pthread_cond_signal() :
int pthread_cond_signal(pthread_cond_t *cond);
- Parameter :
cond : condition variable
- Return Value :
On success, 0 is returned ; otherwise, an error number shall be returned to indicate
the error.
CODE:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int done = 1;
// Thread function
void* foo()
// acquire a lock
pthread_mutex_lock(&lock);
if (done == 1) {
done = 2;
pthread_cond_wait(&cond1, &lock);
else {
pthread_cond_signal(&cond1);
// release lock
pthread_mutex_unlock(&lock);
printf("Returning thread\n");
return NULL;
// Driver code
int main()
// Create thread 1
sleep(4);
// Create thread 2
pthread_join(tid2, NULL);
return 0;
Output:
pallavi@ubuntu:~/Desktop/OS$ ./exp8.3
Returning thread
Returning thread
Experiment No. : 10
5.2 DESCRIPTION
One of the simplest methods for memory allocation is to divide memory into several
fixed-sized partitions. Each partition may contain exactly one process. In this
multiple-partition method, when a partition is free, a process is selected from the
input queue and is loaded into the free partition. When the process terminates, the
partition becomes available for another process. The operating system keeps a table
indicating which parts of memory are available and which are occupied. Finally,
when a process arrives and needs memory, a memory section large enough for this
process is provided. When it is time to load or swap a process into main memory,
and if there is more than one free block of memory of sufficient size, then the
operating system must decide which free block to allocate. Best-fit strategy chooses
the block that is closest in size to the request. First-fit chooses the first available
block that is large enough. Worst-fit chooses the largest available block.
5.3 PROGRAM
5.3.1 WORST-FIT
#include<stdio.h>
#include<conio.h>
#define max 25
void main()
{
int frag[max],b[max],f[max],i,j,nb,nf,temp;
static int bf[max],ff[max];
clrscr();
OUTPUT
Fragme
File No File Size Block No Block Size nt
1 1 1 5 4
2 4 3 7 3
2 BEST-FIT
#include<stdio.h>
#include<conio.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];
clrscr();
INPUT
Enter the number of blocks: 3
Enter the number of files: 2
OUTPUT
Fragme
File No File Size Block No Block Size nt
1 1 2 2 1
2 4 1 5 1
3. FIRST-FIT
#include<stdio.h>
#include<conio.h>
#define max 25
void main()
{
int frag[max],b[max],f[max],i,j,nb,nf,temp,highest=0;
static int bf[max],ff[max];
clrscr();
for(j=1;j<=nb;j++)
{
if(bf[j]!=1) //if bf[j] is not allocated
{
temp=b[j]-f[i];
if(temp>=0)
if(highest<temp)
{
ff[i]=j;
highest=temp;
}
}
}
frag[i]=highest;
bf[ff[i]]=1;
highest=0;
}
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]);
getch();
}
INPUT
Enter the number of blocks: 3
Enter the number of files: 2
OUTPUT
Fragme
File No File Size Block No Block Size nt
1 1 3 7 6
2 4 1 5 1
Experiment No. : 9
DESCRIPTION
Page replacement is basic to demand paging. It completes the separation between
logical memory and physical memory. With this mechanism, an enormous virtual
memory can be provided for programmers on a smaller physical memory. There are
many different page-replacement algorithms. Every operating system probably has
its own replacement scheme.
A FIFO replacement algorithm associates with each page the time when that page
was brought into memory. When a page must be replaced, the oldest page is chosen.
If the recent past is used as an approximation of the near future, then the page that
has not been used for the longest period of time can be replaced. This approach is
the Least Recently Used (LRU) algorithm.
LRU replacement associates with each page the time of that page's last use. When a
page must be replaced, LRU chooses the page that has not been used for the longest
period of time.
Optimal page replacement algorithm has the lowest page-fault rate of all algorithms
and will never suffer from Belady's anomaly. The basic idea is to replace the page
that will not be used for the longest period of time. Use of this page-replacement
algorithm guarantees the lowest possible page fault rate for a fixed number of
frames. Unfortunately, the optimal page-replacement algorithm is difficult to
implement, because it requires future knowledge of the reference string.
PROGRAM
int main()
{
for(i=0;i<n;i++)
scanf("%d",&rs[i]);
scanf("%d",&f);
for(i=0;i<f;i++)
m[i]=-1;
for(k=0;k<f;k++)
{
if(m[k]==rs[i])
break;
if(k==f)
{
m[count++]=rs[i];
pf++;
}
for(j=0;j<f;j++)
printf("\t%d",m[j]);
if(k==f)
printf("\tPF No. %d",pf);
printf("\n");
if(count==f)
count=0;
}
printf("\n The number of Page Faults using FIFO are %d\n",pf);
return 0;
INPUT
pallavi@ubuntu:~/Desktop/OS$ gcc -o exp9 exp9.c
pallavi@ubuntu:~/Desktop/OS$ ./exp9
Output
int main()
scanf("%d",&n);
scanf("%d",&rs[i]);
flag[i]=0;
}
scanf("%d",&f);
for(i=0;i<f;i++)
{
count[i]=0;
m[i]=-1;
}
for(i=0;i<n;i++)
{
for(j=0;j<f;j++)
if(m[j]==rs[i])
{
flag[i]=1;
count[j]=next;
next++;
}
if(flag[i]==0)
{
if(i<f)
m[i]=rs[i];
count[i]=next;
next++;
}
else
min=0;
for(j=1;j<f;j++)
if(count[min] > count[j])
min=j;
m[min]=rs[i];
count[min]=next;
next++;
}
pf++;
for(j=0;j<f;j++)
printf("%d\t", m[j]);
if(flag[i]==0)
printf("\n");
}
OUTPUT
pallavi@ubuntu:~/Desktop/OS$ gcc -o exp9.1 exp9.1.c
pallavi@ubuntu:~/Desktop/OS$ ./exp9.1
Enter the length of reference string -- 20
Enter the reference string -- 7 8 5 4 6 5 4 1 32 1 3 9 7 8 1 2 3 5 6 4
Enter the number of frames -- 3
if(flag1 == 0){
for(j = 0; j < no_of_frames; ++j){
if(frames[j] == -1){
faults++;
frames[j] = pages[i];
flag2 = 1;
break;
}
}
}
if(flag2 == 0){
flag3 =0;
if(flag3 ==0){
max = temp[0];
pos = 0;
printf("\n");
return 0;
}
OUTPUT
pallavi@ubuntu:~/Desktop/OS$ gcc -o exp9.2 exp9.2.c
pallavi@ubuntu:~/Desktop/OS$ ./exp9.2
Enter number of frames: 3
Enter number of pages: 10
Enter page reference string: 1 4 5 2 4 5 6 3 1 5
1 -1 -1
1 4 -1
1 4 5
2 4 5
2 4 5
2 4 5
6 4 5
3 4 5
1 4 5
1 4 5