A developer uses POSIX shared memory to share a large data structure between two processes but implements no locks or semaphores. This design will most likely result in:
ACorrect behavior — shared memory handles access coordination automatically through the OS
BA compilation error — the POSIX API requires synchronization primitives to be declared at allocation time
CRace conditions — both processes access the same memory concurrently without coordination, risking corrupted or inconsistent data
DA kernel panic — the OS detects unsynchronized access to shared memory and terminates the processes
Shared memory gives multiple processes direct access to the same physical memory pages with no kernel mediation after setup. This is precisely analogous to two threads sharing a variable without a mutex. Without explicit synchronization (locks, semaphores, memory barriers), one process may read while another is mid-write, producing corrupted data. The OS provides no automatic protection — synchronization is entirely the programmer's responsibility. This is the most common misconception about shared memory IPC.
Question 2 Multiple Choice
Why does a Unix pipe block the writer process when the pipe buffer is full?
ATo prevent the kernel from allocating memory beyond the system's physical capacity
BTo implement automatic flow control, preventing a fast producer from outrunning a slow consumer
CBecause the read end of the pipe has closed, signaling the consumer has finished
DBecause pipes hold only a single message at a time and must be emptied before the next write
Pipe blocking implements automatic back-pressure. The pipe has a fixed kernel buffer (typically 64 KB on Linux). When it fills, the writer blocks until the reader consumes enough data to free space; when it empties, the reader blocks until the writer produces more. This flow control is what makes the Unix shell pipeline model elegant — `grep | sort | uniq` doesn't require the programmer to manually coordinate timing between the three processes. The blocking is a feature, not a limitation.
Question 3 True / False
Message passing through pipes is generally faster than shared memory for exchanging large amounts of data, because the kernel manages most data movement.
TTrue
FFalse
Answer: False
The opposite is true. Message passing requires two data copies: from the sender's address space into the kernel buffer, then from the kernel buffer into the receiver's address space. For large or frequent transfers, this copying overhead is significant. Shared memory eliminates both copies after initial setup — processes access the same physical memory directly with no kernel involvement. The performance advantage of shared memory over message passing for large transfers is precisely the reason shared memory exists as a separate IPC mechanism, despite its more complex synchronization requirements.
Question 4 True / False
Standard Unix pipes are bidirectional — a process can both write to and read from the same pipe for two-way communication with another process.
TTrue
FFalse
Answer: False
Standard Unix pipes are unidirectional byte streams: one end is the write end, the other is the read end. A single pipe only moves data in one direction. Full-duplex communication between two processes requires either two pipes (one for each direction) or a different mechanism such as sockets, which support bidirectional data flow. This is why shell pipelines use a separate pipe for each connection between processes.
Question 5 Short Answer
Explain the fundamental tradeoff between message passing and shared memory as IPC mechanisms, and describe when you would choose each.
Think about your answer, then reveal below.
Model answer: Message passing routes data through the kernel — data is copied from sender's address space into a kernel buffer, then into the receiver's. This is simple and safe (the kernel mediates all access, preventing simultaneous access issues), but the two-copy overhead adds latency and CPU cost for large or frequent transfers. Shared memory maps the same physical pages into multiple address spaces for zero-copy direct access — much faster, but requires explicit programmer-managed synchronization (locks, semaphores) to prevent race conditions. Choose message passing when simplicity and safety matter more than throughput, or when data volumes are modest; choose shared memory when transfer performance is critical and you can manage synchronization complexity.
This tradeoff mirrors the core tension in concurrent systems design between safety and performance. Kernel mediation provides safety guarantees at the cost of overhead; bypassing the kernel gives performance but transfers the safety responsibility to the programmer. The right choice depends on whether the performance benefit of eliminating kernel copying justifies the added synchronization complexity — and on whether the communicating processes are on the same machine (shared memory possible) or across machines (message passing via sockets required).