Search Knowledge

© 2026 LIBREUNI PROJECT

Operating Systems Internals / Advanced Topics & UNIX Deep Dive

UNIX Interprocess Communication (IPC)

UNIX Interprocess Communication (IPC)

Interprocess Communication (IPC) is the mechanism provided by an operating system that allows processes to exchange data and synchronize execution. Because UNIX and POSIX-compliant systems enforce strict virtual memory isolation, processes cannot access each other’s memory space directly. They must use kernel-mediated IPC channels to collaborate.

Core IPC Mechanisms

UNIX provides several distinct methodologies for communication between processes, each designed for different synchronization paradigms, data structures, and namespaces.

Anonymous Pipes

Anonymous pipes provide a unidirectional byte stream from one process to another. They are created in memory and do not exist on disk. A pipe consists of a pair of file descriptors managed by the kernel, where data written to the write end is queued until read from the read end.

The following C program demonstrates unidirectional parent-child communication using an anonymous pipe:

#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    int fd[2];
    char write_buf[] = "IPC Pipe Transit";
    char read_buf[32];

    /* Create pipe: fd[0] is read end, fd[1] is write end */
    if (pipe(fd) == -1) {
        return 1;
    }

    if (fork() == 0) {
        close(fd[0]); /* Close unused read end */
        write(fd[1], write_buf, strlen(write_buf) + 1);
        close(fd[1]);
    } else {
        close(fd[1]); /* Close unused write end */
        read(fd[0], read_buf, sizeof(read_buf));
        printf("Parent read: %s\n", read_buf);
        close(fd[0]);
    }
    return 0;
}

Pipes are fundamental to command line composition, allowing the stdout of one process to flow into the stdin of another (e.g., ls -l | grep ".txt").

Named Pipes (FIFOs)

While anonymous pipes require processes to share a common ancestor (e.g., parent-child relationship), Named Pipes (also known as FIFOs) allow unrelated processes to communicate. A FIFO exists as a special file in the file system but behaves as a pipe in memory.

# Example: Creating and communicating via a FIFO named pipe
mkfifo /tmp/custom_fifo

# Process A writes to the FIFO (blocks until a reader opens it)
echo "FIFO Message Exchange" > /tmp/custom_fifo &

# Process B reads from the FIFO
cat < /tmp/custom_fifo

Unix Domain Sockets

UNIX Domain Sockets (UDS) enable bidirectional data exchange between processes running on the same physical host. Unlike network sockets that use IP addresses and ports, UNIX domain sockets use pathnames in the file system (e.g., /var/run/docker.sock) as their endpoints, enforcing access security using standard POSIX file permissions.

The following C snippet shows how to define and bind a UNIX domain socket address structure:

#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>

/* Example: Initializing a UNIX Domain Socket Address Structure */
void init_socket_address(struct sockaddr_un *addr, const char *socket_path) {
    memset(addr, 0, sizeof(struct sockaddr_un));
    addr->sun_family = AF_UNIX;
    strncpy(addr->sun_path, socket_path, sizeof(addr->sun_path) - 1);
}

Shared Memory

Shared memory is the fastest form of IPC. The kernel maps a segment of physical memory directly into the virtual address space of multiple processes. This allows processes to read and write directly to the same memory addresses without copying data through kernel buffers.

The following C code maps a POSIX shared memory object:

#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

/* Example: Setting up and mapping a POSIX Shared Memory segment */
void* setup_shared_memory(const char *name, size_t size) {
    /* Create or open the shared memory object */
    int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) return MAP_FAILED;

    /* Configure segment size */
    if (ftruncate(shm_fd, size) == -1) return MAP_FAILED;

    /* Map segment into the process address space */
    return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
}

Because shared memory does not enforce implicit read/write synchronization, developers must use synchronization primitives like semaphores or mutexes to prevent race conditions.

Exercise: Selecting the Right IPC

Evaluate your understanding of IPC constraints and selection criteria in the exercises below:

Case Study Setup

A backend systems architect is designing an architecture where a web server process and a database-logging process must constantly exchange structured telemetry. Both processes execute on the same physical host. The security team mandates that interaction must be restricted using standard file-system user permissions. The development team wants to avoid dealing with manual memory synchronization (like mutexes) to prevent race conditions.

Given these constraints, which IPC mechanism should the architect select?

Creating a POSIX Named Pipe (FIFO)

/* C command to create a named pipe at the specified path */
#include <sys/types.h>
#include <sys/stat.h>

int status = ("/tmp/my_fifo", 0666);

References & Further Reading

For additional details and specifications on IPC APIs, consult the following sources:

  • Stevens, W. R. (1999). UNIX Network Programming, Volume 2: Interprocess Communications (2nd ed.). Prentice Hall. (The definitive guide to UNIX IPC systems).
  • Kerrisk, M. (2010). The Linux Programming Interface. No Starch Press. (Covering Chapter 43: Pipes and FIFOs, Chapter 48: POSIX IPC, and Chapter 57: Sockets: UNIX Domain).
  • shm_open(3) Manual Page. Linux man-pages project.
  • mkfifo(3) POSIX Programmer’s Manual. IEEE / The Open Group.