Definition
Inter-process Communication (IPC) is a mechanism that allows processes to exchange data and signals with each other. Since processes are isolated (for security and stability), IPC provides controlled ways for processes to cooperate, share information, and synchronize their activities. IPC is essential for multi-process applications like client-server systems, pipes, and distributed computing.
Why Inter-Process Communication?
Use Cases
- Data Exchange: Process A needs data from Process B
- Resource Sharing: Multiple processes need same file
- Synchronization: Process B waits for Process A to complete
- Cooperation: Multiple processes work on same task
- Client-Server: Client process requests service from server process
- Producer-Consumer: One process produces, another consumes
Real-World Examples
- Web Browser: HTML parser (process 1) sends data to JavaScript engine (process 2)
- Database: Client process (SQL query) → Server process (process query) → Client gets result
- Compilation: Compiler (preprocessor) → Compiler (main) → Linker → Executable
Models of IPC
Model 1: Shared Memory
How it works:
- Processes share common memory region
- Any process can read/write to shared memory
- Very fast communication
Characteristics:
- Fast: Direct memory access, no kernel involvement
- Complex: Must handle synchronization (locks, semaphores)
- Large Data: Good for large data transfer
Problems:
- Race Condition: Both processes write simultaneously → corrupted data
- Cache Inconsistency: Each CPU has own cache → different values
Solution: Use synchronization primitives (locks, semaphores)
Model 2: Message Passing
How it works:
- Processes exchange messages through kernel
- Each message has sender, receiver, content
- Kernel handles delivery
Characteristics:
- Safe: Kernel controls all communication
- Slow: Kernel overhead on each message
- Simple: No explicit synchronization needed
- Works Across Network: Can send messages over network
Operations:
- Process A calls
send(message, ProcessB) - Kernel copies message to buffer
- Process B calls
receive(message) - Kernel copies message from buffer to B
IPC Methods
1. Pipes
What: One-way communication channel between processes
How Created: pipe() system call creates two file descriptors (read end, write end)
Characteristics:
- Unidirectional: Data flows one direction only
- Sequential: Data read in order received
- Byte Stream: No message boundaries
- Limited Capacity: Fixed buffer size (typically 64KB)
Usage: Unix Shell: command1 | command2
- command1’s stdout → pipe → command2’s stdin
- Example: cat file.txt | grep “error”
Limitations:
- Only between related processes (parent-child)
- For unrelated processes, use named pipes (FIFOs)
2. Named Pipes (FIFOs)
What: Pipe with name in file system, allows unrelated processes to communicate
How Created: mkfifo() creates named pipe
Characteristics:
- Named: Appears as file in file system
- Persistent: Exists until deleted (unlike pipes)
- Unidirectional: One direction like pipes
- FIFO: First-In-First-Out order
Usage:
$ mkfifo /tmp/myfifo
$ process1 > /tmp/myfifo &
$ process2 < /tmp/myfifo
3. Message Queues
What: Queues of messages that processes can send and receive
How Created: msgget() creates message queue
Characteristics:
- Structured: Messages have type and content
- Asynchronous: Sender continues after sending (not blocked)
- Persistent: Survives process termination
- Multicast: Multiple receivers can read same queue
Operations:
msgsnd(): Send message to queuemsgrcv(): Receive message from queuemsgctl(): Control queue operations
Advantage over pipes: Can read specific message types
4. Sockets
What: Bidirectional communication endpoint, like telephone
How Created: socket() creates endpoint
Characteristics:
- Bidirectional: Two-way communication
- Network Ready: Works across network
- Protocol-Based: Uses TCP/IP, UDP, Unix domain, etc.
- Flexible: Byte stream or datagram
Types:
- Stream Socket (TCP): Reliable, ordered delivery, like phone call
- Datagram Socket (UDP): Unreliable, fast, like postcard
- Unix Domain Socket: Fast, local machine only
Usage:
- Web client-server (HTTP over TCP)
- Real-time apps (UDP)
- Local IPC (Unix domain sockets)
5. Shared Memory
What: Memory segment shared by multiple processes
How Created: shmget() creates shared memory segment
Characteristics:
- Fast: No kernel overhead after attachment
- Large Data: Efficient for large data transfer
- Requires Sync: Must use locks/semaphores
- Persistent: Survives process termination
Operations:
shmget(): Create or access shared memoryshmat(): Attach shared memory to processshmdt(): Detach shared memoryshmctl(): Control shared memory
Memory Layout:
Process A Shared Memory Process B
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Private │ │ Shared │ │ Private │
│ Memory │───>│ Memory │<────│ Memory │
│ │ │ │ │ │
└─────────────┘ └──────────────┘ └─────────────┘
6. Semaphores
What: Synchronization primitive, not IPC, but essential for shared memory IPC
Usage with IPC:
- Control access to shared memory
- Coordinate processes
- Ensure data consistency
Example: Without semaphore: P1: read count → modify → write count P2: read count → modify → write count Result: Lost updates (race condition)
With semaphore: P1: wait(semaphore) → read count → modify → write count → signal(semaphore) P2: wait(semaphore) → [blocked until P1 signals] → read count → etc. Result: Safe, coordinated access
Comparison of IPC Methods
| Method | Speed | Setup | Complex | Network | Use Case |
|---|---|---|---|---|---|
| Pipes | Fast | Easy | Simple | No | Shell commands |
| Named Pipes | Fast | Easy | Simple | No | Unrelated processes |
| Sockets | Slow | Medium | Medium | Yes | Network communication |
| Message Queue | Medium | Medium | Medium | No | Structured messages |
| Shared Memory | Very Fast | Hard | Complex | No | Large fast data transfer |
Synchronization Issues with IPC
Problem: Race Condition
Shared Counter = 0
Process A: Process B: read count (0) read count (0) add 1 = 1 add 1 = 1 write count (1) write count (1)
Expected result: 2 Actual result: 1 (one increment lost!)
Solution: Mutual Exclusion (Mutex)
Process A: Process B: lock(mutex) try to lock(mutex) → BLOCKED read count (0) add 1 = 1 write count (1) unlock(mutex) now lock acquired read count (1) add 1 = 2 write count (2) unlock(mutex)
Result: 2 ✓ Correct
Producer-Consumer Problem
Scenario
Producer Process: Generates data items Consumer Process: Uses data items Buffer: Shared between them
Requirements:
- Producer waits if buffer full
- Consumer waits if buffer empty
- Only one process accesses buffer at time
Solution with Semaphores
Semaphore empty = N (initially full buffer space) Semaphore full = 0 (initially no items) Semaphore mutex = 1 (initially unlocked)
Producer: wait(empty) // if buffer full, wait wait(mutex) // lock buffer [produce data, put in buffer] signal(mutex) // unlock buffer signal(full) // signal that data available
Consumer: wait(full) // if buffer empty, wait wait(mutex) // lock buffer [consume data from buffer] signal(mutex) // unlock buffer signal(empty) // signal that space available
Advantages of IPC
- Modularity: Separate concerns into different processes
- Fault Isolation: One process crash doesn’t affect others
- Concurrency: Processes work independently and concurrently
- Reusability: Processes can be reused in different contexts
- Scalability: Can run processes on different machines (for network IPC)
- Security: Processes can have different privilege levels
Disadvantages
- Complexity: IPC adds complexity
- Overhead: Context switching and kernel involvement
- Deadlock Risk: Processes waiting on each other
- Debugging: Hard to debug multi-process systems
- Performance: Slower than single process communication
- Resource Usage: Each process uses more memory
Summary
IPC is essential for multi-process systems. Different IPC methods suit different scenarios: pipes for shell commands, sockets for network, shared memory for fast local communication. Understanding IPC synchronization issues (race conditions, deadlocks) is critical for building correct concurrent systems.