Phase 39
Unix Domain Sockets
The OS supports `AF_UNIX` (Unix domain) sockets for high-performance local inter-process communication. Programs can create stream and datagram sockets bound to filesystem paths. `socketpair()` creates connected pairs for parent-child IPC after `fork()`. This is the primary IPC mechanism on Linux, used by D-Bus, X11, systemd, PostgreSQL, Docker, and many other systems.
Learning goal
Understand why Unix domain sockets exist: local IPC without network overhead.
Category
infrastructure
Components touched
Builds on
Unlocked by this phase
Why this phase matters
The OS supports AF_UNIX (Unix domain) sockets for high-performance local inter-process communication. Programs can create stream and datagram sockets bound to filesystem paths. socketpair() creates connected pairs for parent-child IPC after fork(). This is the primary IPC mechanism on Linux, used by D-Bus, X11, systemd, PostgreSQL, Docker, and many other systems.
How it works in m3OS
The roadmap entry defines the learning scope for this phase; a deeper implementation doc has not been matched yet.
How it builds on earlier phases
This phase builds on Filesystem Enhancements and turns that foundation into Unix Domain Sockets.
Implementation outline
- Add
UnixSocketstruct andUNIX_SOCKET_TABLEinkernel/src/net/unix.rs. - Add
FdBackend::UnixSocketvariant to process FD infrastructure. - Extend
sys_socket()to acceptAF_UNIXand allocate Unix sockets. - Implement
sys_socketpair()with real Unix socket pairs (replace pipe delegation). - Implement
bind()for named sockets (create socket file in VFS). - Implement
connect()to named sockets (find socket file, establish connection). - Implement
listen()+accept()for stream sockets. - Implement
read()/write()for connected stream sockets. - Implement
sendto()/recvfrom()for datagram sockets. - Add poll/epoll support for Unix socket fds.
- Add
shutdown()support for Unix sockets. - Test:
socketpair()for parent-child communication. - Test: named stream socket server/client.
- Test: datagram socket message boundary preservation.
Task progress snapshot
131 of 131 tracked tasks are complete.
Documentation targets
- Documentation deliverables have not been listed yet.
Deferred follow-on work
- SCM_RIGHTS (file descriptor passing)
- SCM_CREDENTIALS (credential passing)
- SOCK_SEQPACKET
- Abstract namespace sockets
- SO_PEERCRED
- Autobind
- sendmsg/recvmsg with ancillary data
Source materials
Important code
Code spotlight cards
Code spotlight
Define `UnixSocketType` and `UnixSocketState` enums
and datagram sockets have fundamentally different behavior (connection-oriented. Why it matters: These enums drive all state-machine transitions. Stream. Focus on `UnixSocketType` and `UnixSocketState` in `kernel/src/net/unix.rs` while you trace the snippet.
// A.1 — UnixSocketType and UnixSocketState enums
// ===========================================================================
/// Unix socket type: stream (connection-oriented) or datagram (connectionless).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnixSocketType {
Stream,
Datagram,
} Code spotlight
Add `FdBackend::UnixSocket` variant
poll() based on the FdBackend variant. A new variant is needed so the syscall. Why it matters: The FD table dispatches read(), write(), close(), and. Focus on `FdBackend::UnixSocket` and `read` in `kernel/src/process/mod.rs` while you trace the snippet.
/// Backing store for an open file descriptor.
#[derive(Clone)]
pub enum FdBackend {
/// FD 1/2 stdout/stderr — writes go to serial output.
Stdout,
/// FD 0 stdin — reads block until data is available from the kernel stdin buffer.
Stdin,
/// Read-only static ramdisk file (pointer + length into kernel .rodata).
Ramdisk {
content_addr: usize,
content_len: usize,
},
/// Writable tmpfs file, identified by its path (e.g. "foo/bar.txt"
/// relative to tmpfs root — no leading `/tmp/`).
Tmpfs { path: String },
/// FAT32 on-disk file (Phase 24). Stores the relative path within /data,
/// the start cluster, file size, and parent directory cluster.
Fat32Disk {
path: String,
start_cluster: u32,
file_size: u32,
dir_cluster: u32,
},
/// ext2 on-disk file (Phase 28). Stores the root-relative path Code spotlight
Route `read()` and `write()` syscalls for Unix sockets
writes via standard read(fd, buf, len) and write(fd, buf, len). These must. Why it matters: Once a Unix stream socket is connected, userspace reads and. Focus on `read` and `write` in `kernel/src/arch/x86_64/syscall.rs` while you trace the snippet.
#[allow(dead_code)]
const NEG_EAGAIN: u64 = (-11_i64) as u64; Key files
- kernel/src/net/unix.rs — New struct in kernel/src/net/unix.rs managing the state machine for each Unix domain
- kernel/src/net/mod.rs — The existing SOCKET_TABLE in kernel/src/net/mod.rs and FdBackend::Socket handle
- kernel-core/src/pipe.rs — Uses ring buffer patterns from pipes (kernel-core/src/pipe.rs) for socket data buffers.
How real OSes differ
- **SCM_RIGHTS** — Linux passes file descriptors between processes over Unix sockets.
- **SCM_CREDENTIALS** — Linux passes sender's PID/UID/GID as ancillary data.
- **SOCK_SEQPACKET** — Connection-oriented with message boundaries (combines stream reliability with datagram framing).
- **Abstract namespace** — Linux-specific sockets without filesystem entries (`\0name`).
- **Autobind** — Kernel assigns abstract addresses automatically.
- **SO_PEERCRED** — Query connected peer's credentials via `getsockopt()`.
- **sendmsg/recvmsg** — Scatter-gather I/O with ancillary data (control messages).
Success criteria
- `socketpair(AF_UNIX, SOCK_STREAM, 0, sv)` creates a working connected pair.
- A server can `bind` + `listen` + `accept` on a named socket path.
- A client can `connect` to the named socket and exchange data bidirectionally.
- `poll()` and `epoll` work with Unix domain socket fds.
- Datagram sockets preserve message boundaries.
- `unlink()` removes a named socket from the filesystem.
- Socket file permissions are enforced (non-root cannot connect to root-owned socket).
- `shutdown()` half-close works (SHUT_RD, SHUT_WR, SHUT_RDWR).
- Non-blocking mode (`O_NONBLOCK`) works for Unix sockets.
- All existing tests pass without regression.
Related phases
Keep exploring the roadmap
Phase 38
CompleteFilesystem Enhancements
The filesystem supports symlinks, hard links, `umask`-backed creation defaults, the remaining Unix permission semantics needed for symlink-aware metadata and directory listing, a `/proc` filesystem for process introspection, and basic device nodes (`/dev/null`, `/dev/zero`, `/dev/urandom`, `/dev/full`). These are the filesystem primitives that Unix tools and build systems assume exist.
Phase 40
CompleteThreading Primitives
The OS supports kernel-level threads via `clone()` with `CLONE_THREAD` and `CLONE_VM`. Multiple threads share an address space and can synchronize via `futex()`. Thread-local storage works via `arch_prctl(ARCH_SET_FS)`. This enables multi-threaded C programs and improves musl libc compatibility (which uses threads internally even for single-threaded programs).