05 Ipc
05 Ipc
05 Ipc
cross-address-space IPC
e.g. pipes, message passing
shared
data
plus plus
shared memory IPC shared memory IPC shared memory IPC
between user threads In OS user between user threads
of a process user of a process
space space
IPC via shared data – processes share an address space – we have covered:
1. shared data is a passive object accessed via concurrency-controlled operations:
conditional critical regions, monitors, pthreads, Java
2. active objects (shared data has a managing process/thread)
Ada select/accept and rendezvous
3. lock-free programming
To set up a pipe a process makes a pipe system call and is returned two file descriptors
in its open file table. It then creates, using fork two children who inherit all the parent’s
open files, including the pipe’s two descriptors.
Typically, one child process uses one descriptor to write bytes into the pipe
and the other child process uses the other descriptor to read bytes from the pipe.
Hence: pipes can only be used between processes with a common ancestor.
waitMess ( )
A before B
sendMess (ptr)
sendMess ( )
avoids buffering . = potential delay
waitMess (ptr)
A B
. = potential delay
sendMess (ptr)
.
waitMess (ptr)
.
waitMess (ptr) sendMess (ptr)
2. Erlang processes are lightweight (language-level, not OS) and share no common resources.
New processes can be forked (spawned), and execute in parallel with the creator:
Pid = spawn ( Module, FunctionName, ArgumentList )
returns immediately – doesn’t wait for function to be evaluated
process terminates when function evaluation completes
Pid returned is known only to calling process (basis of security)
Pid is a first class value that can be put into data structures and passed in messages
Erlang came from Ericsson and was developed for telecommunications applications.
It is becoming increasingly popular and more widely used.
The syntax for receiving messages is (recall guarded commands and Ada active objects):
receive
Message1 ( when Guard1) ->
Actions1 ;
Message2 ( when Guard2 ) ->
Actions2 ;
..........
end
Each process has a mailbox – messages are stored in it in arrival order.
Message1 and Message2 above are patterns that are matched against messages in the process
mailbox. A process executing receive is blocked until a message is matched.
When a matching MessageN is found and the corresponding GuardN succeeds, the message is
removed from the mailbox, the corresponding ActionsN are evaluated and receive returns
the value of the last expression evaluated in ActionsN.
Programmers are responsible for making sure that the system does not fill up
with unmatched messages.
Messages can be received from a specific process if the sender includes its Pid
in the pattern to be matched: Pid ! {self( ), abc}
receive {Pid, Msg}
Client:
PidBufferManager ! { self ( ), put, <data> }
PidBufferManager ! { self ( ), get, <pointer for returned data> }
Buffer Manager:
receive {PidClient, put, <data> } (buffer not full)
insert item into buffer and return
The first part develops the language and includes many small programs, including
distributed programs, e.g. page 89 (page 100 in pdf) has the server and client code,
with discussion, for an ATM machine.
The second part contains worked examples of applications, not available free.
A free version of Erlang can be obtained from
http://www.ericsson.com/technology/opensource/erlang
Erlang also works cross-address-space, and distributed.
• = potential delay
- after writing a message into a mailbox the sending process/thread loses all rights to that data
- the receiver/reading-process gains rights. Based on linear type theory.
- in the current shared memory implementation, threads share an address space
messages are not physically copied but pointers are used i.e. mailboxes contain pointers
- good performance demonstrated for large numbers of threads cf. Erlang
A B
.
sendMess (ptr)
.
waitMess (ptr)
.
waitMess (ptr)
.
sendMess (ptr)
.= potential delay
Historically, synchronous systems were favoured for theoretical modelling and proof.
e.g. occam was based on the CSP formalism, Hoare 1978
occam enforces static declaration of processes - more applicable to embedded systems than
general purpose ones: “assembly language for the transputer”.
Current applications need dynamic creation of large numbers of threads.
In practice, asynchronous systems are used when large scale and distribution are needed.