0% found this document useful (0 votes)
14 views47 pages

UNIT-3

The document discusses system modeling in the context of deadlock, defining deadlock as a situation where processes are waiting for resources held by each other, leading to a complete halt in execution. It outlines the necessary conditions for deadlock, techniques for prevention, avoidance, and detection, as well as recovery methods when deadlocks occur. Key concepts include safe and unsafe states, resource allocation graphs, and strategies for breaking deadlocks through process termination or resource preemption.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views47 pages

UNIT-3

The document discusses system modeling in the context of deadlock, defining deadlock as a situation where processes are waiting for resources held by each other, leading to a complete halt in execution. It outlines the necessary conditions for deadlock, techniques for prevention, avoidance, and detection, as well as recovery methods when deadlocks occur. Key concepts include safe and unsafe states, resource allocation graphs, and strategies for breaking deadlocks through process termination or resource preemption.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 47

UNIT-3

System Model
For the purposes of deadlock discussion, a system can be modeled as a
collection of limited resources, which can be partitioned into different
categories, to be allocated to a number of processes, each having different
needs.

 Resource categories may include memory, printers, CPUs, open files, tape
drives, CD-ROMS, etc.
 By definition, all the resources within a category are equivalent, and a
request of this category can be equally satisfied by any one of the
resources in that category. If this is not the case ( i.e. if there is some
difference between the resources within a category ), then that category
needs to be further divided into separate categories. For example,
"printers" may need to be separated into "laser printers" and "color inkjet
printers".
 Some categories may have a single resource.
 In normal operation a process must request a resource before using it, and
release it when it is done, in the following sequence:
1. Request - If the request cannot be immediately granted, then the
process must wait until the resource(s) it needs become available.
For example the system calls open( ), malloc( ), new( ), and
request( ).
2. Use - The process uses the resource, e.g. prints to the printer or
reads from the file.
3. Release - The process relinquishes the resource. so that it becomes
available for other processes. For example, close( ), free( ), delete( ),
and release( ).
 For all kernel-managed resources, the kernel keeps track of what
resources are free and which are allocated, to which process they are
allocated, and a queue of processes waiting for this resource to become
available. Application-managed resources can be controlled using
mutexes or wait( ) and signal( ) calls, ( i.e. binary or counting semaphores.
)
 A set of processes is deadlocked when every process in the set is waiting
for a resource that is currently allocated to another process in the set (and
which can only be released when that other waiting process makes
progress).

INTRODUCTION TO DEADLOCK
Every process needs some resources to complete its execution. However, the
resource is granted in a sequential order.

1. The process requests for some resource.


2. OS grant the resource if it is available otherwise let the process waits.
3. The process uses it and release on the completion.

A Deadlock is a situation where each of the computer process waits for a


resource which is being assigned to some another process. In this situation,
none of the process gets executed since the resource it needs, is held by some
other process which is also waiting for some other resource to be released.

Let us assume that there are three processes P1, P2 and P3. There are three
different resources R1, R2 and R3. R1 is assigned to P1, R2 is assigned to P2
and R3 is assigned to P3.

After some time, P1 demands for R2 which is being used by P2. P1 halts its
execution since it can't complete without R2. P2 also demands for R3 which is
being used by P3. P2 also stops its execution because it can't continue without
R3. P3 also demands for R1 which is being used by P1 therefore P3 also stops
its execution.

In this scenario, a cycle is being formed among the three processes. None of the
process is progressing and they are all waiting. The computer becomes
unresponsive since all the processes got blocked.
Example of Deadlock

 A real-world example would be traffic, which is going only in one


direction.
 Here, a bridge is considered a resource.
 So, when Deadlock happens, it can be easily resolved if one car backs up
(Preempt resources and rollback).
 Several cars may have to be backed up if a deadlock situation occurs.
 So starvation is possible.

Necessary Conditions

The deadlock situation can only arise if all the following four conditions hold
simultaneously:

1.Mutual Exclusion

According to this condition, at least one resource should be non-shareable (non-


shareable resources are those that can be used by one process at a time.)
2. Hold and wait

According to this condition, A process is holding at least one resource and is


waiting for additional resources.

3. NO preemption

Resources cannot be taken from the process because resources can be released
only voluntarily by the process holding them.

4. Circular wait

In this condition, the set of processes are waiting for each other in the circular
form.

The above four conditions are not completely independent as the circular wait
condition implies the hold and wait condition. We emphasize on the fact that all
four conditions must hold for a deadlock.

Deadlock conditions can be avoided with the help of a number of methods. Let
us take a look at some of the methods.

VARIOUS TECHNIQUES FOR DEADLOCK PREVENTION

Deadlock prevention means placing restrictions on resource requests so that


deadlocks cannot occur. Denying at least any one of the conditions of deadlock
can prevent deadlock.

 Mutual Exclusion
There should be a resource that can only be held by one process at a time.
In the diagram below, there is a single instance of Resource 1 and it is
held by Process 1 only.
 Preventing Hold and Wait
A process can hold multiple resources and still request more resources
from other processes which are holding them. In the diagram given below,
Process 2 holds Resource 2 and Resource 3 and is requesting the
Resource 1 which is held by Process 1.

 Preventing Non Preemption


A resource cannot be preempted from a process by force. A process can
only release a resource voluntarily. In the diagram below, Process 2
cannot preempt Resource 1 from Process 1. It will only be released when
Process 1 relinquishes it voluntarily after its execution is complete.

 Preventing Circular Wait


A process is waiting for the resource held by the second process, which is
waiting for the resource held by the third process and so on, till the last
process is waiting for a resource held by the first process. This forms a
circular chain. For example: Process 1 is allocated Resource2 and it is
requesting Resource 1. Similarly, Process 2 is allocated Resource 1 and it
is requesting Resource 2. This forms a circular wait loop.

DEADLOCK AVOIDANCE AND DETECTION


Deadlock prevention algorithm ensure that at least one of the four necessary
conditions for deadlocks namely mutual exclusion, hold and wait, no pre-
emption and circular wait do not hold.

The disadvantage with the prevention algorithms is poor resource utilization


and thus reduced system throughout.

An alternate method is to avoid deadlocks. In this case additional a prior


information about the usage of resources by processes is required. This
information helps to decide on whether a process should wait for a resource or
not. Decision about a request is based on all the resources available, resources
allocated to processes, future requests and releases by processes.

A deadlock avoidance algorithm requires each process to make known in


advance the maximum number of resources of each time that it may need. Also
known is the maximum number of resource of each type available. Using both
the above a prior knowledge, deadlock avoidance algorithm ensures that a
circular wait condition never occurs.

Safe State and Unsafe State

A state is safe if the system can allocate resources to each process (up to its
maximum requirement) in some order and still avoid a deadlock. Formally, a
system is in a safe state only, if there exists a safe sequence. So a safe state is
not a deadlocked state and conversely a deadlocked state is an unsafe state.

In an Unsafe state, the operating system cannot prevent processes from


requesting resources in such a way that any deadlock occurs. It is not necessary
that all unsafe states are deadlocks; an unsafe state may lead to a deadlock.

The above Figure shows the Safe, unsafe, and deadlocked state spaces

Deadlock Avoidance Example

Let us consider a system having 12 magnetic tapes and three processes P1, P2,
P3. Process P1 requires 10 magnetic tapes, process P2 may need as many as 4
tapes, process P3 may need up to 9 tapes. Suppose at a time to, process P1 is
holding 5 tapes, process P2 is holding 2 tapes and process P3 is holding 2 tapes.
(There are 3 free magnetic tapes)
Processes Maximum Needs Current Needs
So at

P1 10 5

P2 4 2

P3 9 2

time t0, the system is in a safe state. The sequence is <P2, P1, P3> satisfies the
safety condition. Process P2 can immediately be allocated all its tape drives and
then return them. After the return the system will have 5 available tapes, then
process P1 can get all its tapes and return them (the system will then have 10
tapes); finally, process P3 can get all its tapes and return them (The system will
then have 12 available tapes).

A system can go from a safe state to an unsafe state. Suppose at time t1, process
P3 requests and is allocated one more tape. The system is no longer in a safe
state. At this point, only process P2 can be allocated all its tapes. When it
returns them the system will then have only 4 available tapes. Since P1 is
allocated five tapes but has a maximum of ten so it may request 5 more tapes. If
it does so, it will have to wait because they are unavailable. Similarly, process
P3 may request its additional 6 tapes and have to wait which then results in a
deadlock.

The mistake was granting the request from P3 for one more tape. If we made P3
wait until either of the other processes had finished and released its resources,
then we could have avoided the deadlock.

Note: In a case, if the system is unable to fulfill the request of all processes
then the state of the system is called unsafe.
The main key of the deadlock avoidance method is whenever the request is
made for resources then the request must only be approved only in the case if
the resulting state is a safe state.

DEADLOCK DETECTION
If a system does not employ either a deadlock-prevention or deadlock-
avoidance algorithm, then there are chances of occurrence of a deadlock.

In this case, the system may provide two things:

 An algorithm is used to examines the state of the system in order to


determine whether a deadlock has occurred.

 An algorithm that is used to recover from the deadlock.

Thus order to get rid of deadlocks the operating system periodically checks the
system for any deadlock. After Finding the deadlock the operating system will
recover from it using recovery techniques.

Now, the main task of the operating system is to detect the deadlocks and this is
done with the help of Resource Allocation Graph.

The RAG is a directed graph consisting of vertices and directed edges. The
vertex set is partitioned into two types, a subset representing processes and
another subset representing resources. Pictorially, the resources are represented
by rectangles with dots within, each dot representing an instance of the resource
and circles represent processes.

A directed edge from a process to a resource (Pi->Ri) signifies a request from a


process Pi for an instance of the resource Rj and Pi is waiting for Rj. A directed
edge from a resource to a process (Rj->Pi) indicates that an instance of the
resource Rj has been allotted to process Pi. Thus a RAG consists of vertices
which include resources and processes and directed edged which consist of
request edges and assignment edges. A request edge is introduced into the
graph when a process requests for a resource. This edge is converted into an
assignment edge when the resource is granted. When the process releases the
resource, the assignment edge is deleted.

Consider the following system:

There are 3 processes P1, P2 and P3

Resources R1, R2, R3 and R4 have instances 1,2,1 and 3 respectively.

P1 is holding R2 and waiting for R1.

P2 is holding R1, R2 and is waiting for R3.

P3 is holding R3.

The RAG for system in the above situation is as shown in fig

If a RAG has no cycle (a closed loop in the direction of the edges), then the
system is not in a state of deadlock. If on the other hand, there are cycles, then a
deadlock may exist. If there are only single instances of each resource type,
then a cycle in a RAG is a necessary and sufficient condition for existence of a
deadlock.

In the system, there may exist a number of instances and according to them,
there are two types of resource vertices and these are single instances and
multiple instances.
Single Instance

In a single instance resource type, there is a single dot inside the box. The
single dot mainly indicates that there is one instance of the resource.

Multiple Instance

In multiple instance resource types, there are multiple dots inside the box, and
these Multiple dots indicate that there are multiple instances of the resources.

Single Instance RAG Example

Processes P1, P2 and P3 are deadlock and are in a circular wait. P2 is waiting
for R3 held by P3. P3 is waiting for P1 or P2 to release R2. So also P1 is
waiting for P2 to release R1.

Here two cycles exists.

P1->R1->P2->R3->P3->R2->P1

P2->R3->P3->R2->P2

fig: RAG with deadlock


Multiple Instance RAG Example

If there are multiple instances of resources types, then a cycle does not
necessarily imply a deadlock. Here a cycle is a necessary condition but not a
sufficient condition for the existence of a deadlock. Here also there is a cycle.

P1->R1->P3->R2->P1

Suppose there are four processes P1, P2, P3, P4 and there are two instances of
resource R1 and two instances of resource R2:

One instance of R2 is assigned to process P1 and another instance of R2 is


assigned to process P4, Process P1 is waiting for resource R1.

One instance of R1 is assigned to Process P2 while another instance of R2 is


assigned to process P3, Process P3 is waiting for resource R2.

The cycle does not imply a deadlock because an instance of R1 released by P2


could be assigned to P1 or instance of R2 released by P4 could be assigned to
P3 there by breaking the cycle.
RECOVERING FROM DEADLOCK
Once a deadlock has been detected, it must be broken. Breaking a deadlock
may be manual by the operator when informed of the deadlock or automatically
by the system. There exist two options for breaking deadlocks.
1. Abort one or more processes to break the circular-wait condition
causing deadlock.
2. Pre-empting resources from one or more processes which are
deadlock.

1. Process Termination
In order to eliminate deadlock by aborting the process, we will use one of two
methods given below. In both methods, the system reclaims all resources that
are allocated to the terminated processes.

 Aborting all deadlocked Processes Clearly, this method is helpful in


breaking the cycle of deadlock, but this is an expensive approach. This
approach is not suggestable but can be used if the problem becomes very
serious. If all the processes are killed then there may occur insufficiency
in the system and all processes will execute again from starting.
 Abort one process at a time until the elimination of the deadlock
cycle This method can be used but we have to decide which process to
kill and this method incurs considerable overhead. The process that has
done the least amount of work is killed by the Operating system firstly.

2. Resource Preemption

To eliminate deadlocks using resource preemption, we preepmt some


resources from processes and give those resources to other processes. This
method will raise three issues –

(a)Selecting a victim:
We must determine which resources and which processes are to be preempted
and also the order to minimize the cost.

(b)Rollback:
We must determine what should be done with the process from which
resources are preempted. One simple idea is total rollback. That means abort
the process and restart it.

(c)Starvation:
In a system, it may happen that same process is always picked as a victim. As
a result, that process will never complete its designated task. This situation is
called Starvation and must be avoided. One solution is that a process must be
picked as a victim only a finite number of times.

Prevention, avoidance and detection are the three basic approaches to handle
deadlocks. But they do not encompass all the problems encountered. Thus a
combined approach of all the three basic approaches is used.
Process Management and Synchronization
The Critical Section Problem
Process synchronization refers to the idea that multiple processes are to join
up or handshake at a certain point, in order to reach an agreement or commit to
a certain sequence of action. Coordination of simultaneous processes to
complete a task is known as process synchronization.
The critical section problem
Consider a system, assume that it consisting of n processes. Each process
having a segment of code. This segment of code is said to be critical section.
E.G: Railway Reservation System.
Two persons from different stations want to reserve their tickets, the train
number, destination is common, the two persons try to get the reservation at the
same time. unfortunately, the available berths are only one, both are trying for
that berth.
It is also called the critical section problem. solution is when one process is
executing in its critical section, no other process is to be allowed to execute in
its critical section.
The critical section problem is to design a protocol that the processes can use to
cooperate. Each process must request permission to enter its critical section.
The section of code implementing this request is the entry section. The
critical section may be followed by an exit section. The remaining code is
the remainder section.
A solution to the critical section problem must satisfy the following 3
requirements:
1.mutual exclusion:
Only one process can execute their critical section at any time.
2.Progress:
When no process is executing a critical section for a data, one of the
processes wishing to enter a critical section for data will be granted entry.
3.Bounded wait:
No process should wait for a resource for infinite amount of time.
Critical section:
The portion in any program that acceses a shared resource is called as critical
section (or) critical region.
Peterson’s solution:
Peterson solution is one of the solutions to critical section problem involving
two processes. This solution states that when one process is executing its
critical section then the other process executes the rest of the code and vice
versa.
Peterson solution requires two shared data items:
turn: indicates whose turn it is to enter into the critical section. If turn == i,
then process i is allowed into their critical section.
flag: indicates when a process wants to enter into critical section. when
process i wants to enter their critical section, it sets flag[i] to true.
do {
flag[i]= TRUE; turn = j;
while (flag[j] && turn == j);
critical section
flag[i] = FALSE;
remainder section
} while (TRUE);

Synchronization hardware

In a uniprocessor multi-programmed system, mutual exclusion can be obtained


by disabling the interrupts before the process enters its critical section and
enabling them after it has exited the critical section.
Disable interrupts
Critical section
Enable interrupts
Once a process is in critical section it cannot be interrupted. This solution
cannot be used in multiprocessor environment. since processes run
independently on different processors.
In multiprocessor systems, Testandset instruction is provided, it
completes execution without interruption. Each process when entering their
critical section must set lock, to prevent other processes from entering their
critical sections simultaneously and must release the lock when exiting their
critical sections.
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
A process wants to enter critical section and value of lock is false then
testandset returns false and the value of lock becomes true. thus for other
processes wanting to enter their critical sections testandset returns true and the
processes do busy waiting until the process exits critical section and sets the
value of lock to false.

Definition:
boolean TestAndSet(boolean&lock)
{
boolean temp=lock;
Lock=true;
return temp;
}
Algorithm for TestAndSet
do
{
while testandset(&lock)
//do nothing
//critical section
lock=false
remainder section
}while(TRUE);
Swap instruction can also be used for mutual exclusion Definition
Void swap(boolean &a, boolean &b)
{
boolean temp=a;
a=b;
b=temp;
}
Algorithm
Do
{
key=true;
while(key=true)
swap(lock,key);
critical section
lock=false;
remainder section
}while(1);
lock is global variable initialized to false. each process has a local variable key.
A process wants to enter critical section, since the value of lock is false and key
is true.
lock=false
key=true
after swap instruction,
lock=true key=false
now key=false becomes true, process exits repeat-until, and enter into critical
section.
When process is in critical section (lock=true), so other processes wanting to
enter critical section will have
lock=true key=true
Hence they will do busy waiting in repeat-until loop until the process exits
critical section and sets the value of lock to false.

Semaphores

A semaphore is an integer variable and is used for restricting access to a shared


resource in multiprogramming environment. A semaphore value can be altered
by P and V operations. P operation is also known as wait operation and V
operation is also known as signal operation. Any process want to access a
resource, has to perform P operation. Any process while releasing the resource
has to perform V operation.
P operation: wait operation
If s>0 then
Set s to s-1
Else
Block the calling process(i.e., wait for resource)
Endif
V operation: signal operation
If any processes are waiting on s
Start one of these processes
Else
Set s to s+1
Endif
Initially semaphore S value is set to “1”. When a process wants to access a
resource it performs P operation. Suppose a process P0 wants to access
resource, as S value is 1 which is greater than 0 so process can access the
resource. Now process P1 wants resource. Now as S value is less than 0 the
calling process i.e., P1 will be blocked. When P0 wants to release the resource
it will perform V operation. As P1 waiting for resource P1 will get resource
otherwise the S value will be incremented by 1 which indicates resource is free.

Problems:
1. Deadlock
Deadlock occurs when multiple processes are blocked. each waiting for a
resource that can only be freed by one of the other blocked processes.
2. Starvation
one or more processes gets blocked forever and never get a chance to take their
turn in the critical section.

3. Priority inversion
If low priority process is running, medium priority processes are waiting for
low priority process, high priority processes are waiting for medium priority
processes. this is called Priority inversion.
The two most common kinds of semaphores are counting semaphores and
binary semaphores. Counting semaphores represent multiple resources, while
binary semaphores, as the name implies, represents two possible states
(generally 0 or 1; locked or unlocked).

Classic problems of synchronization

1. Bounded-buffer problem
Two processes share a common, fixed –size buffer.
Producer puts information into the buffer, consumer takes it out.
The problem arise when the producer wants to put a new item in the buffer, but
it is already full. The solution is for the producer has to wait until the consumer
has consumed at least one buffer. similarly if the consumer wants to remove an
item from the buffer and sees that the buffer is empty, it goes to sleep until the
producer puts something in the buffer and wakes it up.
The structure of the producer process
do {
// produce an item in nextp wait
(empty);
wait (mutex);
// add the item to the buffer signal
(mutex);
signal (full);
} while (TRUE);
The structure of the consumer process
do
{
wait (full);
wait (mutex);
// remove an item from buffer to nextc signal
(mutex);
signal (empty);
// consume the item in nextc
} while (TRUE);

2. The readers-writers problem


A database is to be shared among several concurrent processes. some processes
may want only to read the database, some may want to update the database. If
two readers access the shared data simultaneously no problem. if a write, some
other process access the database simultaneously problem arised. Writes have
excusive access to the shared database while writing to the database. This
problem is known as readers- writes problem.
First readers-writers problem
No reader be kept waiting unless a writer has already obtained permission to
use the shared resource.
Second readers-writes problem:
Once writer is ready, that writer performs its write as soon as possible.
A process wishing to modify the shared data must request the lock in write
mode. multiple processes are permitted to concurrently acquire a reader-writer
lock in read mode. A reader writer lock in read mode. but only one process may
acquire the lock for writing as exclusive access is required for writers.
Semaphore mutex initialized to 1
Semaphore wrt initialized to 1
Integer read count initialized to 0

The structure of a writer process


do
{
wait (wrt);
// writing is performed
signal (wrt);
} while (TRUE);
The structure of a reader process
do
{
wait (mutex);
readcount ++;
if (readcount == 1)
wait (wrt);
signal (mutex)
// reading is performed
wait (mutex);
readcount - -;
if (readcount == 0)
signal (wrt);
signal (mutex);
} while (TRUE);

Dining Philosophers problem


Five philosophers are seated on 5 chairs across a table. Each philosopher has a
plate full of noodles. Each philosopher needs a pair of forks to eat it. There are
only 5 forks available all together. there is only one fork between any two
plates of noodles.
In order to eat, a philosopher lifts two forks, one to his left and the other to his
right. if he is successful in obtaining two forks, he starts eating after some time,
he stops eating and keeps both the forks down.

What if all the 5 philosophers decide to eat at the same time?


All the 5 philosophers would attempt to pick up two forks at the same time. So,
none of them succeed.
One simple solution is to represent each fork with a semaphore. a philosopher
tries to grab a fork by executing wait() operation on that semaphore. he releases
his forks by executing the signal() operation. This solution guarantees that no
two neighbours are eating simultaneously.
Suppose all 5 philosophers become hungry simultaneously and each grabs his
left fork, he will be delayed forever.
The structure of Philosopher i:
do
{
wait ( chopstick[i] );
wait ( chopStick[ (i + 1) % 5] );
// eat
signal ( chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// think
} while (TRUE);
Several remedies:
 Allow at most 4 philosophers to be sitting simultaneously at the table.
 Allow a philosopher to pickup his fork only if both forks are available.
 An odd philosopher picks up first his left fork and then right fork. an even
philosopher picks up his right fork and then his left fork.

MONITORS

The disadvantage of semaphore is that it is unstructured construct. Wait and


signal operations can be scattered in a program and hence debugging becomes
difficult.
A monitor is an object that contains both the data and procedures needed to
perform allocation of a shared resource. To accomplish resource allocation
using monitors, a process must call a monitor entry routine. Many processes
may want to enter the monitor at the same time. but only one process at a time
is allowed to enter. Data inside a monitor may be either global to all routines
within the monitor (or) local to a specific routine. Monitor data is accessible
only within the monitor. There is no way for processes outside the monitor to
access monitor data. This is a form of information hiding.
If a process calls a monitor entry routine while no other processes are executing
inside the monitor, the process acquires a lock on the monitor and enters it.
while a process is in the monitor, other processes may not enter the monitor to
acquire the resource. If a process calls a monitor entry routine while the other
monitor is locked the monitor makes the calling process wait outside the
monitor until the lock on the monitor is released. The process that has the
resource will call a monitor entry routine to release the resource. This routine
could free the resource and wait for another requesting process to arrive
monitor entry routine calls signal to allow one of the waiting processes to enter
the monitor and acquire the resource. Monitor gives high priority to waiting
processes than to newly arriving ones.
Structure:
monitor monitor-name
{
// shared variable declarations
procedure P1 (…) { …. }
procedurePn (…){……}
Initialization code (…) { … }
}
Processes can call procedures p1, p2, p3……They cannot access the local
variables of the monitor
Schematic view of a Monitor
Monitor with Condition Variables

Monitor provides condition variables along with two operations on them i.e.
wait and signal.
wait(condition variable) signal(condition variable)
Every condition variable has an associated queue. A process calling wait on a
particular condition variable is placed into the queue associated with that
condition variable. A process calling signal on a particular condition variable
causes a process waiting on that condition variable to be removed from the
queue associated with it.
Solution to Producer consumer problem using monitors:
monitor producer consumer
condition full, empty;
int count;
procedure insert(item)
{
if(count==MAX)
wait(full);
insert_item(item);
count=count+1;
if(count==1)
signal(empty);
}
procedure remove()
{
if(count==0)
wait(empty);
remove_item(item);
count=count-1;
if(count==MAX-1) signal(full);
}
procedure producer()
{
producerconsumer.insert(item);
}
procedure consumer()
{
producerconsumer.remove();
}
Solution to dining philosophers problem using monitors
A philosopher may pickup his forks only if both of them are available. A
philosopher can eat only if his two neighbours are not eating. some other
philosopher can delay himself when he is hungry.
Dining philosophers.Take_forks( ) : acquires forks ,which may block the
process.
Eat noodles ( )
Dining philosophers.put_ forks( ): releases the forks.
Resuming processes within a monitor
If several processes are suspended on condition x and x.signal( ) is executed
by some process. Then
how do we determine which of the suspended processes should be resumed
next?
solution is FCFS (process that has been waiting the longest is resumed first).
In many circumstances, such simple technique is not adequate. alternate
solution is to assign priorities and wake up the process with the highest
priority.
Resource allocation using monitor
boolean
inuse=false;
conditionavailable;
//conditionvariable
monitorentry void get resource()
{
if(inuse) //is resource inuse
{
wait(available); wait until available issignaled
}
inuse=true; //indicate resource is now inuse
}
monitor entry void return resource()
{
inuse=false; //indicate resource is not in use
signal(available); //signal a waiting process to proceed
}
IPC between processes on a single computer system and different
systems- using pipes, FIFOs, message queues, shared memory.
Inter process communication (IPC) is used for exchanging data between
multiple threads in one or more processes or programs. The Processes may
be running on single or multiple computers connected by a network.

The IPC mechanisms can be classified into the following categories.

 Pipes
 Files
 Shared memory
 Message passing
 Sockets

A process can be of two types:


 Independent process.
 Co-operating process.

An independent process is not affected by the execution of other processes


while a co-operating process can be affected by other executing processes.
Though one can think that those processes, which are running
independently, will execute very efficiently, in reality, there are many
situations when co-operative nature can be utilized for increasing
computational speed, convenience, and modularity. Inter-process
communication (IPC) is a mechanism that allows processes to communicate
with each other and synchronize their actions. The communication between
these processes can be seen as a method of co-operation between them.
Processes can communicate with each other through both:

1. Shared Memory
2. Message passing

Figure 1 below shows a basic structure of communication between


processes via the shared memory method and via the message passing
method.
An operating system can implement both methods of communication. First,
we will discuss the shared memory methods of communication and then
message passing. Communication between processes using shared memory
requires processes to share some variable, and it completely depends on
how the programmer will implement it. One way of communication using
shared memory can be imagined like this: Suppose process1 and process2
are executing simultaneously, and they share some resources or use some
information from another process. Process1 generates information about
certain computations or resources being used and keeps it as a record in
shared memory. When process2 needs to use the shared information, it will
check in the record stored in shared memory and take note of the
information generated by process1 and act accordingly. Processes can use
shared memory for extracting information as a record from another process
as well as for delivering any specific information to other processes.
Let’s discuss an example of communication between processes using the
shared memory method.

i) Shared Memory Method


Ex: Producer-Consumer problem

There are two processes: Producer and Consumer. The producer produces
some items and the Consumer consumes that item. The two processes share
a common space or memory location known as a buffer where the item
produced by the Producer is stored and from which the Consumer consumes
the item if needed. There are two versions of this problem: the first one is
known as the unbounded buffer problem in which the Producer can keep on
producing items and there is no limit on the size of the buffer, the second
one is known as the bounded buffer problem in which the Producer can
produce up to a certain number of items before it starts waiting for
Consumer to consume it. We will discuss the bounded buffer problem.
First, the Producer and the Consumer will share some common memory,
then the producer will start producing items. If the total produced item is
equal to the size of the buffer, the producer will wait to get it consumed by
the Consumer. Similarly, the consumer will first check for the availability
of the item. If no item is available, the Consumer will wait for the Producer
to produce it. If there are items available, Consumer will consume them.
The pseudo-code to demonstrate is provided below:

Shared Data between the two Processes

 C

#define buff_max 25

#define mod %

struct item{

// different member of the produced data

// or consumed data

---------

// An array is needed for holding the items.

// This is the shared place which will be

// access by both process


// item shared_buff [ buff_max ];

// Two variables which will keep track of

// the indexes of the items produced by producer

// and consumer The free index points to

// the next free index. The full index points to

// the first full index.

int free_index = 0;

int full_index = 0;

Producer Process Code

 C

item nextProduced;

while(1){

// check if there is no space

// for production.
// if so keep waiting.

while((free_index+1) mod buff_max == full_index);

shared_buff[free_index] = nextProduced;

free_index = (free_index + 1) mod buff_max;

Consumer Process Code

 C

item nextConsumed;

while(1){

// check if there is an available

// item for consumption.

// if not keep on waiting for

// get them produced.

while((free_index == full_index);
nextConsumed = shared_buff[full_index];

full_index = (full_index + 1) mod buff_max;

In the above code, the Producer will start producing again when the
(free_index+1) mod buff max will be free because if it it not free, this
implies that there are still items that can be consumed by the Consumer so
there is no need to produce more. Similarly, if free index and full index
point to the same index, this implies that there are no items to consume.

ii) Messaging Passing Method


Now, We will start our discussion of the communication between processes
via message passing. In this method, processes communicate with each
other without using any kind of shared memory. If two processes p1 and p2
want to communicate with each other, they proceed as follows:
 Establish a communication link (if a link already exists, no need to
establish it again.)
 Start exchanging messages using basic primitives.
We need at least two primitives:
– send(message, destination) or send(message)
– receive(message, host) or receive(message)
The message size can be of fixed size or of variable size. If it is of fixed
size, it is easy for an OS designer but complicated for a programmer and if
it is of variable size then it is easy for a programmer but complicated for the
OS designer. A standard message can have two parts: header and body.
The header part is used for storing message type, destination id, source id,
message length, and control information. The control information contains
information like what to do if runs out of buffer space, sequence number,
priority. Generally, message is sent using FIFO style.

Message Passing through Communication Link.


Direct and Indirect Communication link
Now, We will start our discussion about the methods of implementing
communication links. While implementing the link, there are some
questions that need to be kept in mind like :

1. How are links established?


2. Can a link be associated with more than two processes?
3. How many links can there be between every pair of communicating
processes?
4. What is the capacity of a link? Is the size of a message that the link
can accommodate fixed or variable?
5. Is a link unidirectional or bi-directional?

A link has some capacity that determines the number of messages that can
reside in it temporarily for which every link has a queue associated with it
which can be of zero capacity, bounded capacity, or unbounded capacity. In
zero capacity, the sender waits until the receiver informs the sender that it
has received the message. In non-zero capacity cases, a process does not
know whether a message has been received or not after the send operation.
For this, the sender must communicate with the receiver explicitly.
Implementation of the link depends on the situation, it can be either a direct
communication link or an in-directed communication link.
Direct Communication links are implemented when the processes use a
specific process identifier for the communication, but it is hard to identify
the sender ahead of time.
For example the print server.
In-direct Communication is done via a shared mailbox (port), which
consists of a queue of messages. The sender keeps the message in mailbox
and the receiver picks them up.
Message Passing through Exchanging the Messages.
Synchronous and Asynchronous Message Passing:
A process that is blocked is one that is waiting for some event, such as a
resource becoming available or the completion of an I/O operation. IPC is
possible between the processes on same computer as well as on the
processes running on different computer i.e. in networked/distributed
system. In both cases, the process may or may not be blocked while sending
a message or attempting to receive a message so message passing may be
blocking or non-blocking. Blocking is
considered synchronous and blocking send means the sender will be
blocked until the message is received by receiver. Similarly, blocking
receive has the receiver block until a message is available. Non-blocking is
considered asynchronous and Non-blocking send has the sender sends the
message and continue. Similarly, Non-blocking receive has the receiver
receive a valid message or null. After a careful analysis, we can come to a
conclusion that for a sender it is more natural to be non-blocking after
message passing as there may be a need to send the message to different
processes. However, the sender expects acknowledgment from the receiver
in case the send fails. Similarly, it is more natural for a receiver to be
blocking after issuing the receive as the information from the received
message may be used for further execution. At the same time, if the
message send keep on failing, the receiver will have to wait indefinitely.
That is why we also consider the other possibility of message passing.
There are basically three preferred combinations:

 Blocking send and blocking receive


 Non-blocking send and Non-blocking receive
 Non-blocking send and Blocking receive (Mostly used)

In Direct message passing, The process which wants to communicate must


explicitly name the recipient or sender of the communication.
e.g. send(p1, message) means send the message to p1.
Similarly, receive(p2, message) means to receive the message from p2.
In this method of communication, the communication link gets established
automatically, which can be either unidirectional or bidirectional, but one
link can be used between one pair of the sender and receiver and one pair of
sender and receiver should not possess more than one pair of links.
Symmetry and asymmetry between sending and receiving can also be
implemented i.e. either both processes will name each other for sending and
receiving the messages or only the sender will name the receiver for
sending the message and there is no need for the receiver for naming the
sender for receiving the message. The problem with this method of
communication is that if the name of one process changes, this method will
not work.

In Indirect message passing, processes use mailboxes (also referred to as


ports) for sending and receiving messages. Each mailbox has a unique id
and processes can communicate only if they share a mailbox. Link
established only if processes share a common mailbox and a single link can
be associated with many processes. Each pair of processes can share several
communication links and these links may be unidirectional or bi-directional.
Suppose two processes want to communicate through Indirect message
passing, the required operations are: create a mailbox, use this mailbox for
sending and receiving messages, then destroy the mailbox. The standard
primitives used are: send(A, message) which means send the message to
mailbox A. The primitive for the receiving the message also works in the
same way e.g. received (A, message). There is a problem with this mailbox
implementation. Suppose there are more than two processes sharing the
same mailbox and suppose the process p1 sends a message to the mailbox,
which process will be the receiver? This can be solved by either enforcing
that only two processes can share a single mailbox or enforcing that only
one process is allowed to execute the receive at a given time or select any
process randomly and notify the sender about the receiver. A mailbox can
be made private to a single sender/receiver pair and can also be shared
between multiple sender/receiver pairs. Port is an implementation of such
mailbox that can have multiple senders and a single receiver. It is used in
client/server applications (in this case the server is the receiver). The port is
owned by the receiving process and created by OS on the request of the
receiver process and can be destroyed either on request of the same receiver
processor when the receiver terminates itself. Enforcing that only one
process is allowed to execute the receive can be done using the concept of
mutual exclusion. Mutex mailbox is created which is shared by n process.
The sender is non-blocking and sends the message. The first process which
executes the receive will enter in the critical section and all other processes
will be blocking and will wait.
Now, let’s discuss the Producer-Consumer problem using the message
passing concept. The producer places items (inside messages) in the
mailbox and the consumer can consume an item when at least one message
present in the mailbox. The code is given below:
Producer Code

 C

void Producer(void){

int item;

Message m;

while(1){

receive(Consumer, &m);

item = produce();

build_message(&m , item ) ;

send(Consumer, &m);

Consumer Code

 C

void Consumer(void){
int item;

Message m;

while(1){

receive(Producer, &m);

item = extracted_item();

send(Producer, &m);

consume_item(item);

Examples of IPC systems

1. Posix : uses shared memory method.


2. Mach : uses message passing
3. Windows XP : uses message passing using local procedural calls

Communication in client/server Architecture:

There are various mechanism:

 Pipe
 Socket
 Remote Procedural calls (RPCs)
Pipes

Pipe is widely used for communication between two related processes. This
is a half-duplex method, so the first process communicates with the second
process. However, in order to achieve a full-duplex, another pipe is needed.

FIFO:

Communication between two unrelated processes. It is a full-duplex method,


which means that the first process can communicate with the second process,
and the opposite can also happen.

Socket:

The socket is the endpoint for sending or receiving data in a network. This is
true for data sent between processes on the same computer or data sent
between different computers on the same network. Most of the operating
systems use sockets for inter process communication.

Remote Procedural calls (RPCs)

Remote Procedure Call (RPC) is a powerful technique for


constructing distributed, client-server based applications. It is based on
extending the conventional local procedure calling so that the called
procedure need not exist in the same address space as the calling
procedure. The two processes may be on the same system, or they may be
on different systems with a network connecting them.

When making a Remote Procedure Call:


1. The calling environment is suspended, procedure parameters are
transferred across the network to the environment where the procedure is to
execute, and the procedure is executed there.
2. When the procedure finishes and produces its results, its results are
transferred back to the calling environment, where execution resumes as if
returning from a regular procedure call.

NOTE: RPC is especially well suited for client-server (e.g. query-


response) interaction in which the flow of control alternates between the
caller and callee. Conceptually, the client and server do not both execute at
the same time. Instead, the thread of execution jumps from the caller to the
callee and then back again.

Working of RPC
The following steps take place during a RPC:

1. A client invokes a client stub procedure, passing parameters in the


usual way. The client stub resides within the client’s own address space.

2. The client stub marshalls(pack) the parameters into a message.


Marshalling includes converting the representation of the parameters into a
standard format, and copying each parameter into the message.
3. The client stub passes the message to the transport layer, which sends it
to the remote server machine.

4. On the server, the transport layer passes the message to a server stub,
which demarshalls(unpack) the parameters and calls the desired server
routine using the regular procedure call mechanism.

5. When the server procedure completes, it returns to the server stub (e.g.,
via a normal procedure call return), which marshalls the return values
into a message. The server stub then hands the message to the transport
layer.

6. The transport layer sends the result message back to the client transport
layer, which hands the message back to the client stub.

7. The client stub demarshalls the return parameters and execution returns
to the caller.

RPC ISSUES

Issues that must be addressed:

1. RPC Runtime: RPC run-time system is a library of routines and a set of


services that handle the network communications that underlie the RPC
mechanism. In the course of an RPC call, client-side and server-side run-
time systems’ code handle binding, establish communications over an
appropriate protocol, pass call data between the client and server, and
handle communications errors.

2. Stub: The function of the stub is to provide transparency to the


programmer-written application code.

On the client side, the stub handles the interface between the client’s local
procedure call and the run-time system, marshaling and unmarshaling data,
invoking the RPC run-time protocol, and if requested, carrying out some of
the binding steps.

On the server side, the stub provides a similar interface between the run-
time system and the local manager procedures that are executed by the
server.
3. Binding: How does the client know who to call, and where the service
resides?
The most flexible solution is to use dynamic binding and find the server at
run time when the RPC is first made. The first time the client stub is
invoked, it contacts a name server to determine the transport address at
which the server resides.
Binding consists of two parts:

 Naming:
Remote procedures are named through interfaces. An interface
uniquely identifies a particular service, describing the types
and numbers of its arguments. It is similar in purpose to a type
definition in programming languauges.

 Locating:
Finding the transport address at which the server actually resides.
Once we have the transport address of the service, we can send
messages directly to the server.
A Server having a service to offer exports an interface for it. Exporting an
interface registers it with the system so that clients can use it.

A Client must import an (exported) interface before communication can


begin.

Advantages of Remote Procedure Call


Some of the advantages of RPC are as follows −

 Remote procedure calls support process oriented and thread oriented


models.
 The internal message passing mechanism of RPC is hidden from the
user.
 The effort to re-write and re-develop the code is minimum in remote
procedure calls.
 Remote procedure calls can be used in distributed environment as well
as the local environment.
 Many of the protocol layers are omitted by RPC to improve
performance.
Disadvantages of Remote Procedure Call
Some of the disadvantages of RPC are as follows −

 The remote procedure call is a concept that can be implemented in


different ways. It is not a standard.
 There is no flexibility in RPC for hardware architecture. It is only
interaction based.
 There is an increase in costs because of remote procedure call.

You might also like