Windows 95 IPC and Synchronization
Partitioning programs into separate processes results in a number of server processes (spellers, formatters, loggers, etc.) that can be debugged, tested, and tuned independently. A pleasant side-effect of this approach is that the processor can be utilized more fully due to the parallelism of multiple, independent processes doing their work simultaneously. A final benefit, for any OO devotee, is that the process is a unit of reuse similar to a class. It provides an interface but hides its implementation.
Interprocess communication can be loosely defined as the passing of information between two separate processes. Because each process inhabits a separate address space, the operating system must provide support for this communication to bypass the address space boundaries. Windows 95 provides the following mechanisms:
- Anonymous pipes These are used between related processes such as parent and child processes.
- Named pipes Windows 95 supports only client use of a named pipe.
- Mailslots Short messages can be sent in one direction. Mailslots are useful for broadcasting to a workgroup.
- Clipboard, DDE, and OLE These are common IPC methods but they cannot work in character-only applications.
- Shared memory Data segments can be shared (see "Sharing Variables between Win32 Executables," CUJ, March 1997) to allow communication through the shared memory. All access to this memory must be synchronized.
- Memory-mapped files This is a higher-level form of shared memory supported through the virtual memory manager.
A problem arises whenever two or more process use shared memory. This problem also affects threads since any memory that isn't stack-based is implicitly shared. The problem occurs when one thread reads a variable then later updates the variable, but the variable has been changed by a second thread between the read and update. The second thread's value is simply overwritten; it's as if the second thread hadn't modified the variable at all.
Synchronization protects shared data against this problem by preventing threads from accessing data while it is being used by another process. Windows 95 provides the following objects exclusively for synchronization:
- Mutex A mutex can only be owned by one thread at a time.
- Semaphore A semaphore contains a value between 0 and some maximum, n, so it can be owned by at most n threads at one time.
- Event An event notifies threads when a specific event occurs.
Processes and threads gain access to a synchronization object by waiting on it. If the object is signalled then the thread gets ownership of the object (it is no longer signalled) and can continue. Waiting on a synchronization object is efficient since the operating system places waiting threads on a different queue and doesn't schedule them to run until they own the object or they timeout. The thread must remember to release the object so that other waiting threads can own it in turn.
Deadlock occurs when two threads A and B both want to own two synchronization objects, a and b. If A owns a and waits on b, but B owns b and is waiting on a, then deadlock occurs. One thread must release its object so that the other thread can continue. o