This document explains the internal mechanisms CRIU uses to capture the state of opened file descriptors (FDs).
In the Linux kernel, an opened file is represented by a chain of three distinct objects:
pos) and access flags.Crucially, file descriptors are per-task integers that point to these shared “File” objects. When a task calls fork(), the child’s FDs point to the same “File” objects as the parent’s.
Dumping FDs requires CRIU to collect state from both the kernel’s /proc filesystem and the file objects themselves.
CRIU reads /proc/$pid/fd/ and /proc/$pid/fdinfo/ to determine which FD numbers are currently open and to retrieve their basic properties (position and flags).
To perform deeper inspection (like fstat or ioctl), CRIU needs a local copy of the file descriptor. It achieves this by:
SCM_RIGHTS mechanism.To minimize image size and avoid redundant dumps, CRIU must identify if FDs in different tasks (or even the same task) point to the same underlying “File” object. It uses a two-stage optimization:
gen_ids, they are guaranteed to be different.gen_ids match, CRIU uses the kcmp() system call (with the KCMP_FILE flag) to definitively determine if the two descriptors refer to the same kernel “File” object.CRIU stores FD information in a two-tier structure:
fdinfo-$id.img ImageThis per-task image maps task-specific FD numbers to global File IDs. Each entry contains:
fd: The numeric descriptor in the task.id: A unique identifier for the underlying file object.The actual state of the file objects is stored in specialized images based on their type:
reg-files.img: Regular files (includes the path).pipes.img: Pipes and FIFOs.unixsk.img / inetsk.img: Sockets.signalfd.img, eventfd.img, epoll.img, etc.This separation allows CRIU to efficiently handle shared files: multiple fdinfo entries can point to a single entry in a specialized file image.