Interprocess communication (IPC) in Linux refers to various mechanisms that allow processes to exchange data, coordinate actions, and share resources, enabling cooperation and synchronization between independent programs.
Linux provides several built-in IPC mechanisms, each suited to different communication needs:
Signals: Used for sending simple notifications or instructions (such as termination or pausing) between processes. These are lightweight and commonly used for handling asynchronous events.
Pipes: Enable unidirectional data transfer between related processes (typically parent and child). There are:
Anonymous pipes: Used between related processes, created via the pipe() system call.
Named pipes (FIFOs): Used between unrelated processes, created using mkfifo().
Message Queues: Allow asynchronous, buffered communication by sending and receiving messages via a queue, supporting communication between one or multiple processes.
Shared Memory: Enables multiple processes to access and modify a common segment of memory for fast, large-volume data exchange. Synchronization mechanisms (like semaphores or mutexes) are often required to coordinate access and prevent race conditions.
Sockets: Facilitate communication either between processes on the same machine or across different systems, supporting both stream (TCP) and datagram (UDP) modes.
D-Bus: A modern, high-level IPC mechanism mainly used in desktop environments for communication between applications and system services, providing features like event signaling and remote method invocation.
Each mechanism is implemented by the Linux kernel and exposes system calls (such as kill() for signals, pipe(), msgget(), shmget() for message queues and shared memory) so programmers can coordinate process interactions depending on specific requirements.
IPC mechanisms are essential for:
Synchronizing operations (when processes depend on shared resources or must act in concert).
Sharing data efficiently without unnecessary copying.
Enabling modularity in software architecture, such as client-server models or multi-component desktop systems.
For maximum security and efficiency, appropriate permissions, access controls, and synchronization methods must be applied to IPC resources like pipes, message queues, and shared memory.
IPC (Inter-Process Communication) pipes are a powerful mechanism in Linux, allowing data exchange between processes. Pipes are commonly used to send the output of one command directly into another. There are two main types: anonymous pipes and named pipes (FIFOs).
1. Anonymous Pipes
Anonymous pipes are used between related processes (like parent and child processes), typically by the shell.
Example: Basic Use with Shell Commands
ls | grep "txt"
The ls command lists directory contents.
The pipe | sends this output to grep "txt", which filters files ending in .txt.
How It Works
The shell creates a pipe.
Output from ls becomes input to grep.
2. Named Pipes (FIFOs)
Named pipes (or FIFOs) enable communication between unrelated processes.
Creating a Named Pipe
mkfifo mypipe
This command creates a special file called mypipe that acts as a named pipe.
Using a Named Pipe
Open two terminals:
Terminal 1 (Writer):
echo "Hello from Terminal 1!" > mypipe
Terminal 2 (Reader):
cat mypipe
Terminal 1 writes to the pipe.
Terminal 2 reads from the pipe.
3. Viewing Pipe Files
Use ls -l to see your named pipe:
ls -l mypipe
You’ll see something like:
prw-r--r-- 1 user user 0 date time mypipe
The initial p in permissions indicates a pipe.
4. Process Communication Example (With Python)
Anonymous pipes are accessible in code via system calls. For example, in Python:
import os
r, w = os.pipe()
os.write(w, b'Hello Parent!')
print(os.read(r, 20))
This shows how to create a pipe for communication between parts of the same process or different processes.
IPC (Inter-Process Communication) sockets—most often called Unix domain sockets—allow processes on the same Linux system to communicate through a channel-based mechanism, using a file system path as the address. Unlike network sockets that connect machines across networks, Unix domain sockets facilitate communication entirely within the operating system, offering high efficiency, security, and ease of use for local IPC.
Both server and client processes use the socket API with the domain set as AF_UNIX (or AF_LOCAL).
The socket uses a file (e.g., /tmp/my.sock) as its address.
They support both stream-oriented (SOCK_STREAM) and datagram-oriented (SOCK_DGRAM) communication, akin to TCP and UDP respectively.
Processes reference the socket as a file; permissions and ownership are managed through the Linux file system for security.
You can use the socat command to work with Unix domain sockets for IPC in Linux. socat is a powerful tool that establishes bidirectional data streams between two endpoints, including Unix domain sockets. You would have to install socat using your distro's packagae manager.
Here is how you can create and use Unix domain sockets with socat from the terminal:
1. Create a Unix Domain Socket Server
Run this command to create a socket file and listen on it for connections:
socat - UNIX-LISTEN:/tmp/my.sock
UNIX-LISTEN:/tmp/my.sock tells socat to listen on the Unix domain socket /tmp/my.sock.
The socket file is created at /tmp/my.sock.
2. Connect to the Unix Domain Socket as a Client
Open another terminal and connect to the socket with:
socat - UNIX-CONNECT:/tmp/my.sock
UNIX-CONNECT:/tmp/my.sock connects to the socket created by the server.
You can now type messages in either terminal and they will be sent through the socket.
3. Use fork for Handling Multiple Clients
To make the server handle multiple clients (fork a new process for each client), add the fork option:
socat - UNIX-LISTEN:/tmp/my.sock,fork
4. Remove the Socket File When Done
After use, clean up by removing the socket file:
rm /tmp/my.sock
TCP Socket Server with socat
Run this command to start a TCP server listening on port 8080:
socat TCP-LISTEN:8080,fork -
TCP-LISTEN:8080 tells socat to listen on TCP port 8080.
fork allows handling multiple client connections by forking a new process for each.
- connects the socket to standard input/output (your terminal).
The server will print whatever it receives from clients and also send back whatever you type.
TCP Socket Client with socat
In another terminal, connect to the server by running:
socat - TCP4:localhost:8080
- connects your standard input/output (terminal) to the socket.
TCP4:localhost:8080 connects to the TCP server running on port 8080 on your local machine. If connecting to a remote computer, replace localhost with the ip address of that computer you are connecting to.
Now, anything you type in the client terminal will be sent to the server terminal, and any server terminal input will be sent back to the client.
Shared memory in Linux is a mechanism that allows two or more processes to access and manipulate a common block of memory, facilitating fast and efficient inter-process communication (IPC) by enabling direct data sharing without the need for copying between processes. It is the fastest form of IPC because it avoids kernel involvement when data is passed between processes, making it ideal for scenarios requiring high-performance data exchange or collaboration between processes.
In Linux, shared memory segments are created and managed using system calls such as shmget (to create or get a shared memory segment), shmat (to attach the segment to a process's address space), shmdt (to detach it), and shmctl (for control operations). POSIX shared memory APIs such as shm_open and mmap provide an alternative interface for shared memory management. Once attached, processes can read and write to the shared memory segment as if it were their own memory space, with changes immediately visible to all attached processes.
Since shared memory itself does not provide synchronization, processes must use additional synchronization mechanisms like semaphores or mutexes to coordinate access and prevent race conditions.
Key points about shared memory in Linux:
It allows multiple processes to access the same physical memory by mapping shared segments into each process’s virtual address space.
It is used widely for interprocess communication because of its speed and efficiency compared to other IPC methods like pipes or sockets.
Shared memory segments are identified by keys or names to enable multiple processes to locate and attach to them.
Proper permissions are required to create, attach, or control access to shared memory segments.
Synchronization must be handled separately to avoid concurrent access conflicts.
1. Create/Get a Shared Memory Segment: shmget
The shmget system call is used to create a new shared memory segment or access an existing one. This is typically done from a C program, but you can manage shared memory segments using commands like ipcs and manipulate them with ipcrm.
No direct terminal command for shmget exists, but you create or identify shared memory segments via IPC commands.
2. List Shared Memory Segments: ipcs
The ipcs command shows currently active shared memory segments (along with semaphores and message queues).
ipcs -m
(-m lists shared memory segments)
3. Remove Shared Memory Segments: ipcrm
To remove a shared memory segment, use ipcrm with the segment ID found via ipcs.
ipcrm -m <shmid>
This deletes the shared memory segment.
4. Attaching and Detaching Shared Memory in Programs
In C programs, shared memory segments are attached or detached using these system calls:
shmat(shmid, NULL, 0) attaches the shared memory segment identified by shmid to the process's address space.
shmdt(address) detaches it.
D-Bus is a message bus system that provides a way for multiple processes running on the same machine to communicate with each other. It is widely used in Linux desktop environments and system services to facilitate communication between software components.
Key Concepts of D-Bus IPC:
D-Bus is a high-level IPC mechanism based on message passing rather than raw data streams.
It uses a central bus daemon that routes messages between connected processes.
D-Bus defines two main buses: the system bus (for system-level services) and the session bus (for user desktop session applications).
Communication can be one-to-one (method calls with replies) or one-to-many (signals for event notifications).
Messages are well-structured and include object paths, interface names, method names, and parameters.
Example: List all running services on your session bus
gdbus call \
--session \
--dest org.freedesktop.DBus \
--object-path /org/freedesktop/DBus \
--method org.freedesktop.DBus.ListNames
What this does:
--session → talks to your user session bus (not system-wide services).
--dest org.freedesktop.DBus → target the D-Bus daemon itself.
--object-path /org/freedesktop/DBus → path representing the bus object.
ListNames → asks for the names of all currently running D-Bus services.
Expected output (shortened example):
(['org.freedesktop.Notifications',
'org.freedesktop.DBus',
'org.gnome.Shell', ...],)
This is just a list of services/apps connected to your session bus.
Monitor all D-Bus activity
dbus-monitor --session
This will start printing messages whenever apps or the desktop environment communicate over D-Bus — for example, when you open apps or adjust settings.