0% found this document useful (0 votes)
22 views45 pages

6 Ipc

The document discusses interprocess communication and synchronization between processes. It covers three main issues with IPC: 1) how processes pass information, 2) critical section problems when processes access shared resources, and 3) dependency between processes. It then describes different approaches for achieving mutual exclusion when processes access critical sections, including disabling interrupts, lock variables, strict alternation, and Peterson's solution using shared variables to coordinate access. Peterson's solution ensures processes can enter critical sections without blocking or starvation.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views45 pages

6 Ipc

The document discusses interprocess communication and synchronization between processes. It covers three main issues with IPC: 1) how processes pass information, 2) critical section problems when processes access shared resources, and 3) dependency between processes. It then describes different approaches for achieving mutual exclusion when processes access critical sections, including disabling interrupts, lock variables, strict alternation, and Peterson's solution using shared variables to coordinate access. Peterson's solution ensures processes can enter critical sections without blocking or starvation.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 45

OPERATING SYSTEM

LESSON 6 INTERPROCESS COMMUNICATION


INTERPROCESS COMMUNICATION (IPC)
 Processes frequently need to communicate with other
processes. For example, in a shell pipeline, the output of
the first process must be passed to the second process,
and so on down the line. Thus there is a need for
communication between processes.
 There are three issues here:

1.How one process can pass information to another.

2.Critical area problems between processes.

3.Dependency between processes.

2
 The second issue is that two or more processes may get into
each other’s way when starting critical activities. Suppose
two processes each try to grab the last 1 MB of memory.

 The third issue concerns proper sequencing when


dependencies are present: if process A produces data and
process B prints them, B has to wait until A has produced
some data before starting to print.

 Two of these issues are valid for threads. The first one
passing information is easy for threads because they share a
common address space. For other two issues, same
problems exist and same solution can be applied to threads.

3
RACE CONDITIONS
 In some operating systems, processes that are working
together may share some common storage that each one
can read and write. The shared storage may be in main
memory or it may be a shared file.
 To see how interprocess communication works in
practice, let us consider a simple but common example: a
print spooler. When a process wants to print a file, it
enters the file name in a special spooler directory.
Another process, the printer daemon, periodically
checks to see if there are any files to be printed, and if
there are, it prints them and then removes their names
from the directory.
4
 Imagine that our spooler directory has a very large number
of slots, numbered 0, 1, 2, …, each one capable of holding
a file name. Also imagine that there are two shared
variables, out, which points to the next file to be printed,
and in, which points to the next free slot in the directory.

 At a certain instant, slots 0 to 3 are empty (the files have


already been printed) and slots 4 to 6 are full (with the
names of files queued for printing). Suppose, processes A
and B want to queue a file for printing.

5
 Process A reads in and stores the value, 7, in a local variable
called next_free_slot. Just then a clock interrupt occurs and the
CPU switches to process B from Process A. Process B also
reads in, and also gets a 7. It stores it in its local variable
next_free_slot too. At this instant both processes think that the
next available slot is 7. 6
 Process B now continues to run. It stores the name of its file in
slot 7 and updates in to be an 8.
 Process A runs again, starting from the place where it left off.
It looks at next_free_slot, finds a 7 there, and writes its file
name in slot 7, erasing the name that process B just put there.
Then it computes next_free_slot + 1, which is 8, and sets in to
8. The spooler directory is now internally consistent, so the
printer daemon will not notice anything wrong, but process B
will never receive any output.
 Situations like this, where two or more processes are reading
or writing some shared data and the final result depends on
who runs precisely when, are called race conditions.

7
CRITICAL REGIONS
 Sometimes a process have to access shared memory or
files, or doing other critical things that can lead to races.
That part of the program which accesses the shared
memory or file is called the critical region or critical
section.
 We need is mutual exclusion, that is, some way of
making sure that if one process is using a shared variable
or file, the other processes will be excluded from doing
the same thing.
 Achieving mutual exclusion is a major design issue in
any operating system.

8
 We need four conditions to hold to have a good solution
race conditions:
1. Any two processes can not be simultaneously inside their
critical regions.
2. No assumptions may be made about speeds or the number
of CPUs.
3. Any process running outside its critical region can not
block other processes.
4. Any process should not have to wait forever to enter its
critical region.

9
 At time T1 process A enters its critical region
 At T2 process B attempts to enter its critical region but fails. Until
T3 B is temporarily suspended.
 At time T3, B enters its critical region
 At T4, B leaves its critical region

10
MUTUAL EXCLUSION WITH BUSY WAITING

 In this section we will examine various proposals for


achieving mutual exclusion, so that while one process is
busy updating shared memory in its critical region, no
other process will enter its critical region and cause
trouble.

11
1.DISABLING INTERRUPTS

 The simplest solution is to make each process disable all


interrupts just after entering its critical region and re-enable
them just before leaving it. With interrupts disabled, no
clock interrupts can occur.
 The CPU is only switched from process to process as a
result of clock or other interrupts. After interrupts turned off
the CPU will not be switched to another process.

12
 This approach is generally unattractive because it is not a
good idea to give user processes the power to turn off
interrupts.
 Suppose that one of them did it and never turned it on
again? That could be the end of the system.
 Furthermore if the system is a multiprocessor, with two or
more CPUs, disabling interrupts affects only the CPU that
executed the disable instruction. The other ones will
continue running and can access the shared memory.
 It is frequently proper for the kernel itself to disable
interrupts for a few instructions while it is updating
variables or lists.

13
2. LOCK VARIABLES
 This is a software solution. Consider having a single,
shared (lock) variable, initially 0. When a process wants to
enter its critical region, it first tests the lock. If the lock is 0,
the process sets it to 1 and enters the critical region. If the
lock is already 1, the process just waits until it becomes 0.
Thus, a 0 means that no process is in its critical region, and
a 1 means that a process is in its critical region.
 This method also is not a good solution.Suppose that one
process reads the lock and sees that it is 0. Before it can set
the lock to 1, another process is scheduled, runs, and sets
the lock to 1. When the first process runs again, it will also
set the lock to 1, and two processes will be in their critical
regions at the same time. 14
3. STRICT ALTERNATION
 An integer variable turn, initially 0, keeps track of whose
turn it is to enter the critical region and examine or
update the shared memory.

Process 1 Process 2

 Continuously testing a variable until some value appears


is called busy waiting. It should usually be avoided,
since it wastes CPU time.
15
 When process 1 leaves the critical region, it sets turn to 1, to allow
process 2 to enter its critical region. Suppose that process 2 finishes its
critical region, so both processes are in their noncritical regions, with
turn set to 0.
 Suddenly, process 2 finishes its noncritical region before process 1
finishes its noncritical region and goes back to the top of its loop.
Unfortunately, it is not permitted to enter its critical region now,
because turn is 0 and process 1 is busy with its noncritical region. It
hangs in its while loop until process 1 sets turn to 1.
 This situation violates condition 3 set out above: process 1 is being
blocked by a process not in its critical region.

16
4.PETERSON’S SOLUTION

17
 Before using the shared variables each process calls
enter_region with its own process number, 0 or 1, as
parameter. This call may cause it to wait until it is safe to
enter. After it has finished with the shared variables, the
process calls leave_region to indicate that it is done and to
allow the other process to enter.
 Let us see how this solution works. Initially neither process
is in its critical region. Now process 0 calls enter_region. It
indicates its interest by setting its array element and sets turn
to 0. Since process 1 is not interested, enter_region returns
immediately. If process 1 now calls enter_region, it will
hang there until interested[0] goes to FALSE, an event that
only happens when process 0 calls leave_region to exit the
critical region.
18
 Now consider the case that both processes call
enter_region almost simultaneously. Both will store their
process number in turn. Whichever is stored last falls in
loop; the first one is overwritten and lost. Suppose that
process 1 stores last, so turn is 1. When both processes
come to the while statement, process 0 executes it zero
times and enters its critical region. Process 1 loops and
does not enter its critical region until process 0 exits its
critical region.

19
5. THE TSL INSTRUCTION
 Many computers, especially those designed with multiple
processors in mind, have an instruction:
TSL RX,LOCK

 (Test and Set Lock) that works as follows. It reads the


contents of the memory word lock into register RX and
then stores a nonzero value at the memory address lock.
The operations of reading the word and storing into it are
guaranteed to be indivisible—no other processor can
access the memory word until the instruction is finished.
The CPU executing the TSL instruction locks the memory
bus to prohibit other CPUs from accessing memory until 20

it is done.
 When lock is 0, any process may set it to 1 using the TSL
instruction and then read or write the shared memory. When
it is done, the process sets lock back to 0 using an ordinary
move instruction.

21
SLEEP AND WAKEUP
 Both Peterson’s solution and the solution using TSL are
correct, but both have the defect of requiring busy waiting.
When a process wants to enter its critical region, it checks
to see if the entry is allowed. If it is not allowed, the
process just sits in a tight loop waiting until it is allowed.
 Beside of wasting CPU time, this approach can also have
unexpected effects. Consider a computer with two
processes, H, with high priority and L, with low priority.
The scheduling rules are such that H runs whenever it is in
ready state. At a certain moment, with L is in its critical
region, H becomes ready to run. H now begins busy
waiting. Before H is completed, L can not be scheduled. So
L never gets the chance to leave its critical region, so H 22
loops forever.
 Now let me look at some interprocess communication
primitives that block processes when they are not allowed to
enter their critical regions, instead of wasting CPU time in
an empty loop.

 One of the simplest primatives is the pair sleep and wakeup.


Sleep is a system call that causes the caller to block, the
caller is suspended until another process wakes it up. The
wakeup call has one parameter, the process to be awakened.

23
THE PRODUCER-CONSUMER PROBLEM

 As an example of how these primitives can be used, let us


consider the producer-consumer problem. Two processes
share a common, fixed-size buffer. One of them, the
producer, puts information into the buffer, and the other
one, the consumer, takes it out.

24
 Trouble arises when the producer wants to put a new
item in the buffer, but it is already full. The solution is
for the producer to go to sleep, and sleeping producer
will be awakened when the consumer has removed one
or more items. 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.

25
26
 This approach sounds simple enough, but it leads to the
same kinds of race conditions we saw earlier with the
spooler directory. Race conditon can occur because access
to count is unconstrained.

 The following situation could possibly occur. The buffer is


empty and the consumer has just read count to see if it is 0.
At that instant, the scheduler decides to stop running the
consumer temporarily and switches to the producer. The
producer inserts an item in the buffer, increments count, and
notices that it is now 1. Because count was just 0, the
consumer must be sleeping and the producer calls wakeup
to wake the consumer up.
27
 But the consumer is not yet logically asleep, so the
wakeup signal is lost. When the consumer next runs, it
will test the value of count and find it to be 0, and go to
sleep. Sooner or later the producer will fill up the buffer
and also go to sleep. Both will sleep forever.
 A wakeup waiting bit can be added to fix this problem.
When a wakeup is sent to a process that is still awake,
this bit is on. Later, when the process tries to go to sleep,
if the wakeup waiting bit is on, the process will not sleep
and stay awake. Then wakeup waiting bit will be turned
off. But if there are 8,16 or 32 consumers and producers,
it is needed to add wakeup waiting bit for every
consumers and producers.

28
SEMAPHORES
 Semaphore is an integer variable to count the number of
wakeup processes saved for future use. A semaphore
could have the value 0, indicating that no wakeup
processes were saved, or some positive value if one or
more wakeups were pending.
 There are two operations, down (wait) and up(signal)
(generalizations of sleep and wakeup, respectively). The
down operation on a semaphore checks if the value is
greater than 0. If so, it decrements the value and just
continues. If the value is 0, the process is put to sleep
without completing the down for the moment.

29
 The up operation increments the value of the semaphore
addressed. If one or more processes were sleeping on
that semaphore, unable to complete an earlier down
operation, one of them is chosen by the system (e.g., at
random) and is allowed to complete its down.

 Checking the value, changing it and possibly going to


sleep is as a single indivisible atomic action. It is
guaranteed that when a semaphore operation has started,
no other process can access the semaphore until the
operation has completed or blocked.

30
SOLVING THE PRODUCER-CONSUMER
PROBLEM USING SEMAPHORES
 Semaphores solve the lost-wakeup problem. It is
essential that they are implemented in an indivisible way.
The normal way is to implement up and down as system
calls, with the operating system briefly disabling all
interrupts while it is testing the semaphore, updating it,
and putting the process to sleep.
 If multiple CPUs are being used, each semaphore should
be protected by a lock variable, with the TSL instruction
used to make sure that only one CPU at a time examines
the semaphore.

31
 This solution uses three semaphores: one called full for
counting the number of slots that are full, one called empty
for counting the number of slots that are empty, and one
called mutex to make sure the producer and consumer do
not access the buffer at the same time. Full is initially 0,
empty is initially equal to the number of slots in the buffer
(N), and mutex is initially 1.
 The mutex semaphore is used for mutual exclusion. It is
designed to guarantee that only one process at a time will
be reading or writing the buffer and the associated
variables. The other use of semaphores is for
synchronization. The full and empty semaphores are used
to guarantee synchronization. In this case, they ensure that
the producer stops running when the buffer is full, and the
consumer stops running when it is empty. 32
33
MUTEXES
 Mutex is simplified version of the semaphore. When the
semaphore’s ability to count is not needed, mutex can be
used. Mutexes are good for managing mutual exclusion to
some shared resource or piece of code. They are easy and
efficient to implement.
 A mutex is a variable that can be in one of two states:
unlocked or locked. Consequently, only 1 bit is required to
represent it, but in practice an integer often is used, with 0
meaning unlocked and all other values meaning locked.

34
 Two procedures are used with mutexes. When a thread (or
process) needs access to a critical region, it calls
mutex_lock. If the mutex is current unlocked (meaning that
the critical region is available), the call succeeds and the
calling thread is free to enter the critical region.

 If the mutex is already locked, the calling thread is blocked


until the thread in the critical region is finished and calls
mutex_unlock. If multiple threads are blocked on the mutex,
one of them is chosen at random and allowed to acquire the
lock.

35
 Because mutexes are so simple, they can easily be
implemented in user space if a TSL instruction is
available

36
 The code of mutex_lock is similar to the code of
enter_region of TSL Instruction but with a crucial
difference.
 The difference is valid for threads. When enter_region fails
to enter the critical region, it keeps testing the lock
repeatedly (busy waiting). In mutex_lock, when the later
fails to acquire a lock, it calls thread_yield to give up the
CPU to another thread. Consequently there is no busy
waiting.

37
MESSAGE PASSING
 Interprocess communication uses two primitives, send
and receive. They can easily be put into library
procedures, such as
send(destination, &message);
receive(source, &message);
 The former call sends a message to a given destination
and the latter one receives a message from a given
source. If no message is available, the receiver can block
until one arrives. Alternatively, it can return immediately
with an error code.

38
 Message passing systems have many problems, especially if
the communicating processes are on different machines
connected by a network. For example, messages can be lost
on the network. To solve this problem, as soon as a message
has been received, the receiver will send back a special
acknowledgement message. If the sender has not received
the acknowledgement within a certain time interval, it
retransmits the message.
 Now consider what happens if the message itself is received
correctly, but the acknowledgement is lost. The sender will
retransmit the message, so the receiver will get it twice. It is
essential that the receiver is able to distinguish a new
message from the retransmission of an old one.

39
 Usually, this problem is solved by putting consecutive
sequence numbers in each original message. If the receiver
gets a message bearing the same sequence number as the
previous message, it knows that the message is a duplicate
that can be ignored.

 There are also design issues that are important when the
sender and receiver are on the same machine. One of these
is performance. Copying messages from one process to
another is always slower than doing a semaphore operation.

40
THE PRODUCER-CONSUMER
PROBLEM WITH MESSAGE PASSING
 We assume that all messages are the same size and that
messages sent but not yet received are buffered
automatically by the operating system. In this solution, a
total of N messages are used, analogous to the N slots in a
shared memory buffer. The consumer starts out by sending N
empty messages to the producer. Whenever the producer has
an item to give to the consumer, it takes an empty message
and sends back a full one.
 If the producer works faster than the consumer, all the
messages will be full, waiting for the consumer: the producer
will be blocked, waiting for an empty to come back. If the
consumer works faster, all the messages will be empty
waiting for the producer to fill them up: the consumer will 41

be blocked, waiting for a full message.


42
BARRIERS
 Our last synchronization mechanism is intended for
groups of processes rather than two-process producer-
consumer type situations. Some applications are divided
into phases and have the rule that no process may
proceed into the next phase until all processes are ready
to proceed to the next phase. This behavior may be
achieved by placing a barrier at the end of each phase.
When a process reaches the barrier, it is blocked until all
processes have reached the barrier.

43
 We see four processes approaching a barrier (Fig a). After a
while, the first process finishes all the computing during the
first phase. It then executes the barrier primitive, generally
by calling a library procedure. The process is then
suspended. A little later, a second and then a third process
finish the first phase (Fig b). Finally, when the last process,
C, hits the barrier, all the processes are released (Fig c)

44
ANY QUESTION?

45

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy