So, we have looked at several mechanisms of mutual exclusion and interprocess communication. Here are some of the more important ones:
shared-memory | low-level | Disabling interrupts | hardware |
---|---|---|---|
Test-and-set instruction | |||
Peterson's solution | software | ||
other software solutions | |||
high-level | Signals | ||
Semaphores | |||
Monitors | |||
Event counters | |||
no shared memory | Message-passing | ||
Pipes | |||
Remote procedure call |
It should already be clear what we mean by the difference between high-level and low-level primitives: the high-level ones are IPC mechanisms which may be used by user programmes; low-level mechanisms, like disabling the interrupts, are only suitable for use by the OS.
One other thing to say about IPC mechanisms is that they are all sematically equivalent, in that you can build pipes out of shared memory and semaphores; you can build semaphores out of shared memory and the TAS instruction; use messages to implement semaphores and monitors... (section 2.2.9) in the book.
What about the shared-memory/non-shared memory distinction? Well the shared memory mechanisms manage only mutual exclusion and synchronisation---the allow threads to coordinate access to information, but they do not facilitate the transfer of bits. In all the examples we've looked at so far---access to a shared variable, the producer-consumer problem with a shared array---we've been using main memory to actually transfer information between tasks, and using semaphores and things to coordinate access to the memory. (The same approach works with any shared resource: even hardware devices like printers and plotters.) Sometimes that's all the communication which is required.
However, often data must be transferred between cooperating processes. When they do not share access to the same address space (they do not share memory), signals, semaphores, monitors and event counters are not much use, because although they allow the threads of two processes to synchronise, they do not allow any information to be transferred.
Hence message-passing, pipes and remote procedure calls. These mechanisms allow bits to be explicitly transferred from one address space to another.