Skip to content

Day53 - UNIX Domain Socket and Local IPC Architecture

Overview

This chapter introduces UNIX domain socket (AF_UNIX) based local IPC architecture and demonstrates how to build an event-driven middleware daemon on Embedded Linux.

The implementation integrates:

  • UNIX domain socket server/client
  • epoll-based dispatcher
  • multi-client connection management
  • non-blocking socket I/O
  • TX queue and flow control
  • /dev/mypoll kernel event integration
  • local IPC broadcast architecture

AF_UNIX vs TCP Socket

Feature AF_UNIX TCP Socket
Communication scope Local machine only Network
Address File path IP + port
Protocol stack Kernel local IPC TCP/IP
Performance Lower overhead Higher overhead
Security File permission based Network firewall/authentication
Typical usage Local daemon IPC Remote communication

Example UNIX socket path:

/tmp/mypoll.sock

UNIX Domain Socket Architecture

Basic flow

client
AF_UNIX socket
dispatcher daemon
kernel driver (/dev/mypoll)

The userspace daemon acts as a middleware layer between:

  • applications
  • kernel driver
  • event distribution

Event-Driven Dispatcher Architecture

epoll event sources

The daemon integrates multiple event sources into a unified event loop:

epoll_wait()
listen socket
client socket
/dev/mypoll

Dispatcher flow:

epoll_wait()
server_dispatch_event()
event handler

epoll Item Abstraction

Each event source is wrapped by:

struct epoll_item {
    int fd;
    int ep_fd;
    uint32_t events;
    enum epoll_item_type type;
    void *ctx;
};

Benefits:

  • unified event handling
  • clean dispatcher architecture
  • extensible event source management

Multi-Client Architecture

Client structure

struct unix_client {
    int fd;

    struct unix_server *server;

    struct epoll_item item;

    struct tx_queue queue;

    struct unix_client *next;
};

The server maintains:

  • linked-list based client tracking
  • connection lifecycle management
  • TX queue state
  • epoll state

Non-Blocking Socket Design

All sockets are configured with:

O_NONBLOCK

Why:

  • prevent dispatcher blocking
  • allow multi-client concurrency
  • integrate with epoll correctly

Typical recv loop:

recv()
EAGAIN/EWOULDBLOCK
return to event loop

TX Queue Design

Fixed-size TX queue

Instead of dynamic allocation:

malloc()
free()

A fixed queue was used:

struct tx_queue {
    char buf[TX_QUEUE_SIZE];
    size_t len;
    size_t offset;
};

Advantages:

  • deterministic memory usage
  • no heap fragmentation
  • embedded-friendly design
  • simpler lifecycle

TX Queue Operations

Implemented helpers:

  • append
  • consume
  • clear
  • peek
  • read

Example:

client_txq_append()
client_txq_consume()
client_txq_clear()

Flow Control and Backpressure

The server supports:

  • EPOLLIN
  • EPOLLOUT
  • TX queue pressure handling

Flow:

client send command
server append response
EPOLLOUT enabled
send()
consume TX queue

When TX queue becomes full:

disable EPOLLIN
keep EPOLLOUT
drain TX queue
re-enable EPOLLIN

This prevents:

  • memory explosion
  • dispatcher blocking
  • unbounded queue growth

Command Parser Architecture

The server evolved from:

echo server

to:

command parser

Supported commands:

  • start_timer
  • stop_timer
  • trigger
  • echo

Example:

start_timer
write("/dev/mypoll", "start")

/dev/mypoll Integration

The daemon integrates kernel events into the same epoll loop.

Architecture:

kernel event
/dev/mypoll
epoll_wait()
server_broadcast_message()
AF_UNIX clients

This forms a complete middleware architecture.


Middleware Model

Final architecture:

client
AF_UNIX IPC
mypoll_dispatcherd
/dev/mypoll
kernel event
broadcast
all clients

This model is similar to:

  • dbus-daemon
  • bluetoothd
  • NetworkManager
  • modemmanager
  • MQTT broker

Important Concepts Learned

  • AF_UNIX local IPC
  • epoll dispatcher architecture
  • multi-client server design
  • non-blocking socket I/O
  • flow control
  • TX queue management
  • middleware daemon model
  • kernel-to-userspace event forwarding
  • broadcast architecture
  • backpressure handling