Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 41

Artificial Intelligence and Data Science

Year: 2021-2022

Course Name: Operating System Laboratory(AD308)


Class: SY Semester: III

Experiment List

Expt
Title
No. Nature of Experiment

1 Study of different types of Operating System Non-Performing

2 Hands on UNIX/LINUX commands. Performing

3 Shell programming for file handling. Performing


4 Shell script programming using the commands grep, awk andsed. Performing
5 Implementation of different scheduling algorithms. Performing

6 Write a program to implement Producer consumer problem Performing


Write a program to simulate Bankers Algorithm for the purpose of
7 Performing
Deadlock avoidance.
Implementation of synchronization primitives-semaphores, locks and
8 Performing
conditional variables.
9 Implementation of various page replacement policies. Performing
10 Implementation of various memory allocation algorithms. Performing

Signature of the Faculty HOD


Experiment No. : 2

Title: Hands on UNIX/LINUX commands.

COMMANDS:

cat --- for creating and displaying short files


chmod --- change permissions
cd --- change directory
cp --- for copying files
date --- display date
echo --- echo argument
ftp --- connect to a remote machine to download or upload files
grep --- search file
head --- display first part of file
ls --- see what files you have
lpr --- standard print command
more --- use to read files
mkdir --- create directory
mv --- for moving and renaming files
ncftp --- especially good for downloading files via anonymous ftp.
print --- custom print command
pwd --- find out what directory you are in
rm --- remove a file
rmdir --- remove directory
rsh --- remote shell
setenv --- set an environment variable
sort --- sort file
tail --- display last part of file
tar --- create an archive, add or extract files
telnet --- log in to another machine
wc --- count characters, words, lines

1. To create a file.
Syntax: $ cat>filename
Example: $ cat>ex1

2. To view the content of the file.


Syntax: $ cat filename
Example: $ cat ex1

3. To append some details with the existing details in the file


Syntax: $ cat>>filename
Example: $ cat>>ex1

4. To concatenate multiple files


Syntax: $ cat file1 file2 > file3
Example: $ cat computer compiler>world

5. To know the list of all files in directory


Syntax: $ ls

6. To copy the file to another file


Syntax: $ cp source destination
Example: $ cp ex1 ex2

7. To rename the file


Syntax: $ mv oldfile newfile
Example: $ mv ex1 ex3

8. To delete a file
Syntax: $ rm filename
Example: $ rm ex1

9. To delete all files


Syntax: $ rm *

10. To create a directory


Syntax: $ mkdir dirname
11. To change the name of the directory
Syntax: $ cd dirname

12. To remove the directory


Syntax: $ rmdir dirname
Example: $ rmdir flower

13. Echo
i. To display the filename starting with single letter
Syntax: $ echo?

ii. To display the filename starting with two letters


Syntax: $ echo??

iii. To display the filename starting with the letter f


Syntax: $ echo f*

iv. To display the filename ending with letter f.


Syntax: $ echo *f

14. Present Working Directory


i. To display the present working directory
Syntax: $ pwd

ii. To clear the screen


Syntax: $ tput clear

iii. To calculate the values


Syntax: $ bc

iv. Uname: To know your machine name


-n: Tells machine name in network
Syntax: $ uname –n

v. To display the version number of the OS


Syntax: $ uname –r

15. Head
i. To display first 10 lines
Syntax: $ head filename

ii. To display first 6 characters


Syntax: $ head -6c filename

iii. To display 5 lines from 2 files


Syntax: $ head -5 file1 file2

16. To display last 10 lines


Syntax: $ tail filename
Example: $ tail ex3

17. Word Count


i. To display the number of words in a file
Syntax: $ wc filename
Example: $ wc ex1

ii. To display the number of characters in a file


Syntax: $ wc –c filename
Example: $ wc –c ex1

iii. To display the number of lines


Syntax: $ wc –l filename
Example: $ wc –l ex3

General Purpose Utility Commands

COMMANDS:

1. Calendar:
i. To display the calendar.
Syntax: $ cal

ii. To display the previous, current and next month.


Syntax: $ cal -3

iii. To display the current month starting from Sunday.


Syntax: $ cal –s

iv. To display the current month starting from Monday.


Syntax: $ cal –m

2. Date:
i. To display system date.
Syntax: $ date
Output: Tue Jan 20 10:54:25 IST 2009

ii. To display month only.


Syntax: $ date+%m
Output: 01
iii. To display month name and month
Syntax: $date +%h%m
Output: Jan01
iv. To display month name
Syntax: $ date+%h
Output: Jan

v. To display the time in hours


Syntax: $ date+%H
Output: 10
vi. To display the time in minutes
Syntax: $ date+%M
Output: 53

vii. To display the time in AM or PM


Syntax: $ date+%r
Output: 10: 53:24 AM

viii. To display date of month


Syntax: $ date+%d
Output: 20

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)

ii. To display the login user details


Syntax: $ who am i
Output: cs1010

iii. To display my login id


Syntax: $ logname
Output: cs1010

4. MAN
i. It is used to view more details of all the commands
Syntax: $ man command_name
Example: $ man date
Experiment No. : 3

Title: Shell programming for file handling.

 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 Kernel is at the nucleus of a computer. It makes the communication between the


hardware and software possible. While the Kernel is the innermost part of an
operating system, a shell is the outermost one.

 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.

 In Unix, there are two major types of shells −


i. Bourne shell − If you are using a Bourne-type shell, the $ character is the
default prompt.
ii. C shell − If you are using a C-type shell, the % character is the default
prompt.

 The Bourne Shell has the following subcategories −


- Bourne shell (sh)
- Korn shell (ksh)
- Bourne Again shell (bash)
- POSIX shell (sh)

 The different C-type shells follow –


- C shell (csh)
- TENEX/TOPS C shell (tcsh)

 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.

Commands used for file handling:


mkdir
rmdir
touch
cat
rm
cp
mv
ls

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

ii. User-defined variables


- Ex.
name = XYZ
echo “the name is $name”

 How to read user inputs


- Ex.
echo “ Enter name: ”
read name1 name 2 name3
echo “Entered name is : $name1, $name2, $name3”

 How to pass arguments


- echo $1 $2 $3 ‘> echo $1 $2 $3’
 Arithmetic operations
- Ex.
Num1=20
Num2=5
echo $((Num1 + Num2))
echo $((Num1 - Num2))
echo $((Num1 * Num2))
echo $((Num1 / Num2))
echo $((Num1 % Num2))

 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.

1. Options used with grep command:


i. –i
- This option enables the search of string case insensitive.
e.g grep –i “directory” file.txt
ii. –n
- This option prints the number of line searched by search pattern.
e.g grep –n “directory” file.txt
iii. –l
- This option displays the files that contains that contains the given string or
patterns.
e.g. grep –l “directory” *
iv. –w
- By default, grep matches the given string/pattern even if it found as a substring
in a file. The -w option to grep makes it match only the whole words.
v. –o
- It displays only matched string.
e.g grep –o “directory” file.txt
vi. Matching the lines that end with a string : The $ regular expression pattern
specifies
the end of a line. This can be used in grep to match the lines which end with the
given
string or pattern.
e.g. grep “directory$” file.txt
vii. –e
- Using this option, we can give multiple patterns in one command.
e.g grep –e “directory” –e “directories” –e “DIRECTORY” file.txt

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

i. Default behavior of Awk:


- By default Awk prints every line of data from the specified file.
Ex. awk '{print}' dept.txt
ii. Print the lines which match the given pattern:
Ex. awk '/manager/ {print}' dept.txt

iii. Splitting a Line Into Fields :


- For each record i.e line, the awk command splits the record delimited by
whitespace character by default and stores it in the $n variables. If the line has 4
words, it will be stored in $1, $2, $3 and $4 respectively. Also, $0 represents the
whole line.
iv. Built-In Variables In Awk
 NR
NR command keeps a current count of the number of input records.
Records are usually lines.
Ex. awk '{print NR}' dept.txt
awk '{print NR $2}' dept.txt
- To print the first item along with the row number(NR) separated with ” – “ from
each line
awk '{print NR "- " $1 }' dept.txt

 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:

Sed OPTIONS... [SCRIPT] [INPUTFILE...]

i. Replacing or substituting string :


- Sed command is mostly used to replace the text in a file.
- Ex. sed 's/unix/linux/' sed.txt

ii. Replacing the nth occurrence of a pattern in a line :


- Use the /1, /2 etc flags to replace the first, second occurrence of a pattern in a
line. The below command replaces the second occurrence of the word “linux”
with “unix” in a line.
- Ex. sed 's/linux/unix/2' sed.txt

iii. Replacing all the occurrence of the pattern in a line :


- The substitute flag /g (global replacement) specifies the sed command to replace
all the occurrences of the string in the line.
- Ex. sed 's/unix/linux/g' sed.txt

iv. Parenthesize first character of each word :


- This sed example prints the first character of every word in parenthesis.
- Ex. echo "Welcome To The SIT" | sed 's/\(\b[A-Z]\)/\(\1\)/g'

v. Replacing string on a specific line number :


- You can restrict the sed command to replace the string on a specific line number.
An example is
- Ex. $sed '3 s/linux/unix/' sed.txt

vi. Duplicating the replaced line with /p flag


- The /p print flag prints the replaced line twice on the terminal. If a line does not
have the search pattern and is not replaced, then the /p prints that line only once.
- Ex. $sed 's/unix/linux/p' sed.txt

vii. Printing only the replaced lines :


- Use the -n option along with the /p print flag to display only the replaced lines.
Here the -n option suppresses the duplicate rows generated by the /p flag and
prints the replaced lines only one time.
- Ex. sed -n 's/unix/linux/p' sed.txt

viii. Deleting lines from a particular file :


- SED command can also be used for deleting lines from a particular file. SED
command is used for performing deletion operation without even opening the
file
- syntax
sed 'nd' filename.txt
- Ex:
sed '5d' filename.txt
Experiment No. 5

Title: Implementation of different scheduling algorithms.

FCFS CPU SCHEDULING ALGORITHM


 Once the CPU has been allocated to a process, that process keeps the CPU until it
releases the CPU, either by terminating or by requesting I/O.

 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.

SJF CPU SCHEDULING ALGORITHM


 Process that require CPU for shortest amount of time will be first one to get the
CPU.

 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

Title: Write a program to implement Producer consumer problem

Producer Consumer Problem


 A producer process produces information that is consumed by a consumer process.
 We need to make producer and consumer to work concurrently.
 So producer can produce and consumer can consume.
 They have to work concurrently so that, consumer will only consume what is
produced and will not trying to consume what is not produced.
 One solution to the producer-consumer problem uses shared memory.
 To allow producer and consumer processes to run concurrently, we must have
available a buffer of items that can be filled by the producer and emptied by the
consumer.
 Buffer is the place where producer can produce the information and can be consume
by consumer.
 This buffer will reside in a region of memory that is shared by the producer and
consumer processes.
 A producer can produce the one item while the consumer is consuming another.
 The producer and consumer must be synchronized, so that the consumer does not try
to consume an item that has not yet been produced.
 There is a buffer of n slots and each slot is capable of storing one unit of data.
 There are two processes running, namely Producer and Consumer, which are
operating on the buffer.

 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:

• For this we will make the use of three semaphores:

1. m(mutex)

- It is a binary semaphore which is used to acquire and release the lock.

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

- It is counting semaphore whose initial value is 0.


Experiment 7
Title : Write a program to simulate Banker’s algorithm for purpose of
deadlock avoidance.
 The Banker’s algorithm can be used for Deadlock Avoidance in resource
allocation system with multiple instances of each resource type.
 Data structures used to implement Banker’s algorithm
Let n is the number of processes in the system and m is the number of resource
types.
Available:
 A 1-D array of size m indicates the number of available resources of each type.
 If Available[j] = k, means there are k instances of resource type Rj are available.
Max:
 A 2-D array of size n x m that defines the maximum demand of each process.
 If Max[i, j] = k, means process Pi may request at most k instances of resource
type Rj.
Allocation
- It is 2-D array of size ‘n x m’ that defines the number of resources of each
type currently allocated to each process.
- If Allocation[i, j] = k , means process Pi is currently allocated k instances of
resource type Rj.
Need
- It is 2-D array of size ‘n x m’ that indicates the remaining resource need of
each process.
- If Need[i, j] = k, then process Pi currently need k instances of resource type
Rj to complete its execution.
- Need[i, j] = Max[i, j] - Allocation [i, j]
-
 Allocationi specifies the resources currently allocated to process Pi.
 Needi specifies the additional resources that process Pi may still request to
complete its task.

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

 Semaphores are very useful in process synchronization and multithreading


Semaphores is the software solution for process synchronization.
 semaphore is simply a variable which is non-negative and shared between processes.
This variable is used to solve a critical section problem and to achieve process
synchronization in multiprocessing environment.
 A semaphore S is an integer variable that is accessed only through two standard
atomic operations : wait() and signal().

 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

2. Compile the code by linking with -pthread


To lock a semaphore or wait we can use the sem_wait function:
int sem_wait(sem_t *sem);

To release or signal a semaphore, we use the sem_post function:


int sem_post(sem_t *sem);

A semaphore is initialized by using sem_init(for processes or threads) or sem_open


(for IPC).
sem_init(sem_t *sem, int pshared, unsigned int value);

Where,

sem : Specifies the semaphore to be initialized.


pshared : This argument specifies whether or not the newly initialized semaphore is
shared between processes or between threads. A non-zero value means the
semaphore is shared between processes and a value of zero means it is shared
between threads.

value : Specifies the value to assign to the newly initialized semaphore.


To destroy a semaphore, we can use sem_destroy.
sem_destroy(sem_t *mutex);
To declare a semaphore, the data type is sem_t.

int sem_init(sem_t *sem, int pshared, unsigned int value);


The sem_init() function is used to initialise the unnamed semaphore referred to
by sem.

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.

Multiple threads must not initialize the same semaphore.

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;

void* thread(void* arg)


{
//wait
sem_wait(&mutex);
printf("\nEntered..\n");

//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...

2. Synchronization primitive: Lock

 Thread synchronization is defined as a mechanism which ensures that two or more


concurrent processes or threads do not simultaneously execute some particular
program segment known as a critical section.
 Processes’ access to critical section is controlled by using synchronization techniques.
When one thread starts executing the critical section , the other thread should wait
until the first thread finishes.
 If proper synchronization techniques are not applied, it may cause a race condition
where the values of variables may be unpredictable and vary depending on the timings
of context switches of the processes or threads.
 The most popular way of achieving thread synchronization is by using Mutex.
 A Mutex is a lock that we set before using a shared resource and release after using it.
 When the lock is set, no other thread can access the locked region of code.
 So we see that even if thread 2 is scheduled while thread 1 was not done accessing the
shared resource and the code is locked by thread 1 using mutexes then thread 2 cannot
even access that region of code.
 So this ensures synchronized access of shared resources in the code.
Working of Mutex:

 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.

i. int pthread_mutex_init(pthread_mutex_t *restrict mutex, const


pthread_mutexattr_t *restrict attr) : Creates a mutex, referenced by mutex, with
attributes specified by attr. If attr is NULL, the default mutex attribute (NONRECURSIVE)
is used.
- Returned value
If successful, pthread_mutex_init() returns 0, and the state of the mutex becomes initialized
and unlocked.
If unsuccessful, pthread_mutex_init() returns 1.
ii. int pthread_mutex_lock(pthread_mutex_t *mutex) : Locks a mutex object, which
identifies a mutex. If the mutex is already locked by another thread, the thread waits for the
mutex to become available. The thread that has locked a mutex becomes its current owner
and remains the owner until the same thread has unlocked it. 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 a count is incremented and no waiting thread
is posted. The owning thread must call pthread_mutex_unlock() the same number of times
to decrement the count to zero.

Returned value

If successful, pthread_mutex_lock() returns 0.

If unsuccessful, pthread_mutex_lock() returns 1.

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

If successful, pthread_mutex_unlock() returns 0.

If unsuccessful, pthread_mutex_unlock() returns -1

2. int pthread_mutex_destroy(pthread_mutex_t *mutex) : Deletes a mutex object,


which identifies a mutex. Mutexes are used to protect shared resources. mutex is set to an
invalid value, but can be reinitialized using pthread_mutex_init().

Returned value

If successful, pthread_mutex_destroy() returns 0.

If unsuccessful, pthread_mutex_destroy() returns -1.

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;

void* trythis(void* arg)

pthread_mutex_lock(&lock);
unsigned long i = 0;

counter += 1;

printf("\n Job %d has started\n", counter);

for (i = 0; i < (0xFFFFFFFF); i++);

printf("\n Job %d has finished\n", counter);

pthread_mutex_unlock(&lock);

return NULL;

int main(void)

int i = 0;

int error;

if (pthread_mutex_init(&lock, NULL) != 0) {

printf("\n mutex init has failed\n");

return 1;

while (i < 3) {

error = pthread_create(&(tid[i]),

NULL,

&trythis, NULL);

if (error != 0)

printf("\nThread can't be created :[%s]",

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$ gcc -o exp8.2 exp8.2.c -pthread

pallavi@ubuntu:~/Desktop/OS$ ./exp8.2

Job 1 has started

Job 1 has finished

Job 2 has started

Job 2 has finished

Job 3 has started

Job 3 has finished

3. Synchronization primitive: Conditional Variables (wait and signal)


When you want to sleep a thread, condition variable can be used. There is a function
pthread_cond_wait() to wait or sleep.

On the other hand, there is a function pthread_cond_signal() to wake up sleeping or waiting


thread. Threads can wait on a condition variable.

 Syntax of pthread_cond_wait() :
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict
mutex);

where,

cond : condition variable

mutex : is mutex lock

- Return Value :
On success, 0 is returned ; otherwise, an error

number shall be returned to indicate the error.

- The pthread_cond_wait() release a lock specified by mutex and wait on condition


cond variable.

 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.

The pthread_cond_signal() wake up threads waiting for the condition variable.

CODE:

// program to implement cond(), signal() and wait() functions

#include <pthread.h>

#include <stdio.h>

#include <unistd.h>

// Declaration of thread condition variable

pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;


// declaring mutex

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

int done = 1;

// Thread function

void* foo()

// acquire a lock

pthread_mutex_lock(&lock);

if (done == 1) {

// let's wait on condition variable cond1

done = 2;

printf("Waiting on condition variable cond1\n");

pthread_cond_wait(&cond1, &lock);

else {

// Let's signal condition variable cond1

printf("Signaling condition variable cond1\n");

pthread_cond_signal(&cond1);

// release lock

pthread_mutex_unlock(&lock);

printf("Returning thread\n");
return NULL;

// Driver code

int main()

pthread_t tid1, tid2;

// Create thread 1

pthread_create(&tid1, NULL, foo, NULL);

// sleep for 4 sec so that thread 1

// would get a chance to run first

sleep(4);

// Create thread 2

pthread_create(&tid2, NULL, foo, NULL);

// wait for the completion of thread 2

pthread_join(tid2, NULL);

return 0;

Output:

pallavi@ubuntu:~/Desktop/OS$ gcc -o exp8.3 exp8.3.c -pthread

pallavi@ubuntu:~/Desktop/OS$ ./exp8.3

Waiting on condition variable cond1

Signaling condition variable cond1


Returning thread

Returning thread

Returning thread

Experiment No. : 10

Title: Implementation of various memory allocation algorithms..

a) Worst-fit b) Best-fit c) First-fit

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();

printf("\n\tMemory Management Scheme - Worst Fit");


printf("\nEnter the number of blocks:");
scanf("%d",&nb);
printf("Enter the number of files:");
scanf("%d",&nf);
printf("\nEnter the size of the blocks:-\n");
for(i=1;i<=nb;i++)
{
printf("Block %d:",i);
scanf("%d",&b[i]);
}
printf("Enter the size of the files :-\n");
for(i=1;i<=nf;i++)
{
printf("File %d:",i);
scanf("%d",&f[i]);
}
for(i=1;i<=nf;i++)
{
for(j=1;j<=nb;j++)
{
if(bf[j]!=1)
{
temp=b[j]-f[i];
if(temp>=0)
{
ff[i]=j;
break;
}
}
}
frag[i]=temp;
bf[ff[i]]=1;
}
printf("\nFile_no:\tFile_size :\tBlock_no:\tBlock_size:\
tFragement"); for(i=1;i<=nf;i++)
printf("\n%d\t\t%d\t\t%d\t\t%d\t\t%d",i,f[i],ff[i],b[ff[i]],frag[i]);
getch();
}
INPUT
Enter the number of blocks: 3
Enter the number of files: 2

Enter the size of the blocks:-


Block 1: 5
Block 2: 2
Block 3: 7

Enter the size of the files:-


File 1: 1
File 2: 4

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();

printf("\nEnter the number of blocks:");


scanf("%d",&nb);
printf("Enter the number of files:");
scanf("%d",&nf);
printf("\nEnter the size of the blocks:-\n");
for(i=1;i<=nb;i++)
printf("Block %d:",i);scanf("%d",&b[i]);

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


for(i=1;i<=nf;i++)
{
printf("File %d:",i);
scanf("%d",&f[i]);
}
for(i=1;i<=nf;i++)
{
for(j=1;j<=nb;j++)
{
if(bf[j]!=1)
{
temp=b[j]-f[i];
if(temp>=0)
if(lowest>temp)
{
ff[i]=j;
lowest=temp;
}
}
}
frag[i]=lowest;
bf[ff[i]]=1;
lowest=10000;
}
printf("\nFile No\tFile Size \tBlock No\tBlock
Size\tFragment"); for(i=1;i<=nf && ff[i]!=0;i++)
printf("\n%d\t\t%d\t\t%d\t\t%d\t\t%d",i,f[i],ff[i],b[ff[i]],frag[i]);
getch();
}

INPUT
Enter the number of blocks: 3
Enter the number of files: 2

Enter the size of the blocks:-


Block 1: 5
Block 2: 2
Block 3: 7

Enter the size of the files:-


File 1: 1
File 2: 4

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();

printf("\n\tMemory Management Scheme -


Worst Fit"); printf("\nEnter the number of
blocks:"); scanf("%d",&nb);
printf("Enter the number of files:");
scanf("%d",&nf);
printf("\nEnter the size of the blocks:-\n");
for(i=1;i<=nb;i++)
{
printf("Block %d:",i);
scanf("%d",&b[i]);
}
printf("Enter the size of the files :-\n");
for(i=1;i<=nf;i++)
{
printf("File %d:",i);
scanf("%d",&f[i]);
}
for(i=1;i<=nf;i++)
{

for(j=1;j<=nb;j++)
{
if(bf[j]!=1) //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

Enter the size of the blocks:-


Block 1: 5
Block 2: 2
Block 3: 7

Enter the size of the files:-


File 1: 1
File 2: 4

OUTPUT
Fragme
File No File Size Block No Block Size nt
1 1 3 7 6
2 4 1 5 1
Experiment No. : 9

Title: Implementation of various page replacement policies..

a) FIFO b) LRU c) Optimal

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

1 FIFO PAGE REPLACEMENT ALGORITHM


#include<stdio.h>

int main()
{

int i, j, k, f, pf=0, count=0, rs[25], m[10], n;

printf("\n Enter the length of reference string -- ");


scanf("%d",&n);

printf("\n Enter the reference string -- ");

for(i=0;i<n;i++)
scanf("%d",&rs[i]);

printf("\n Enter no. of frames -- ");

scanf("%d",&f);

for(i=0;i<f;i++)
m[i]=-1;

printf("\n The Page Replacement Process is -- \n");


for(i=0;i<n;i++)

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

Enter the length of reference string -- 20

Enter the reference string -- 7 8 5 4 6 4 5 8 9 2 3 1 4 5 7 8 9 4 5 6

Enter no. of frames – 3

Output

The Page Replacement Process is --


7 -1 -1 PF No. 1
7 8 -1 PF No. 2
7 8 5 PF No. 3
4 8 5 PF No. 4
4 6 5 PF No. 5
4 6 5
4 6 5
4 6 8 PF No. 6
9 6 8 PF No. 7
9 2 8 PF No. 8
9 2 3 PF No. 9
1 2 3 PF No. 10
1 4 3 PF No. 11
1 4 5 PF No. 12
7 4 5 PF No. 13
7 8 5 PF No. 14
7 8 9 PF No. 15
4 8 9 PF No. 16
4 5 9 PF No. 17
4 5 6 PF No. 18

The numbers of Page Faults using FIFO are 18

2 LRU PAGE REPLACEMENT ALGORITHM


#include<stdio.h>

int main()

int i, j , k, min, rs[25], m[10], count[10], flag[25], n, f, pf=0, next=1;


printf("Enter the length of reference string -- ");

scanf("%d",&n);

printf("Enter the reference string -- ");


for(i=0;i<n;i++)
{

scanf("%d",&rs[i]);

flag[i]=0;
}

printf("Enter the number of frames -- ");

scanf("%d",&f);

for(i=0;i<f;i++)
{

count[i]=0;

m[i]=-1;
}

printf("\nThe Page Replacement process is -- \n");

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("PF No. -- %d" , pf);

printf("\n");
}

printf("\nThe number of page faults using LRU are %d \n",pf);


return 0;
}

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

The Page Replacement process is --


7 -1 -1 PF No. -- 1
7 8 -1 PF No. -- 2
7 8 5 PF No. -- 3
4 8 5 PF No. -- 4
4 6 5 PF No. -- 5
4 6 5
4 6 5
4 1 5 PF No. -- 6
4 1 32 PF No. -- 7
4 1 32
3 1 32 PF No. -- 8
3 1 9 PF No. -- 9
3 7 9 PF No. -- 10
8 7 9 PF No. -- 11
8 7 1 PF No. -- 12
8 2 1 PF No. -- 13
3 2 1 PF No. -- 14
3 2 5 PF No. -- 15
3 6 5 PF No. -- 16
4 6 5 PF No. -- 17

The number of page faults using LRU are 17

3 Optimal Page Replacement Algorithm


#include<stdio.h>
int main()
{
int no_of_frames, no_of_pages, frames[10], pages[30], temp[10], flag1, flag2,
flag3, i, j, k, pos, max, faults = 0;
printf("Enter number of frames: ");
scanf("%d", &no_of_frames);

printf("Enter number of pages: ");


scanf("%d", &no_of_pages);

printf("Enter page reference string: ");

for(i = 0; i < no_of_pages; ++i){


scanf("%d", &pages[i]);
}

for(i = 0; i < no_of_frames; ++i){


frames[i] = -1;
}

for(i = 0; i < no_of_pages; ++i){


flag1 = flag2 = 0;

for(j = 0; j < no_of_frames; ++j){


if(frames[j] == pages[i]){
flag1 = flag2 = 1;
break;
}
}

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;

for(j = 0; j < no_of_frames; ++j){


temp[j] = -1;

for(k = i + 1; k < no_of_pages; ++k){


if(frames[j] == pages[k]){
temp[j] = k;
break;
}
}
}
for(j = 0; j < no_of_frames; ++j){
if(temp[j] == -1){
pos = j;
flag3 = 1;
break;
}
}

if(flag3 ==0){
max = temp[0];
pos = 0;

for(j = 1; j < no_of_frames; ++j){


if(temp[j] > max){
max = temp[j];
pos = j;
}
}
}
frames[pos] = pages[i];
faults++;
}

printf("\n");

for(j = 0; j < no_of_frames; ++j){


printf("%d\t", frames[j]);
}
}

printf("\n\nTotal Page Faults using optimal page replacement = %d \n", faults);

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

Total Page Faults using optimal page replacement = 7

You might also like