{
  "slug": "process-io-accounting",
  "term": "Process I/O accounting",
  "aliases": [
    "Linux task I/O accounting",
    "/proc/PID/io"
  ],
  "definition": "Process I/O accounting attributes selected I/O activity to a process using counters whose meaning depends on the operation, ownership and accounting layer.",
  "note": "Linux separates read/write-family byte totals from storage-related read_bytes and write_bytes; the latter is charged when pages become dirty. A cached read and a shared memory-mapped write can therefore appear in different counters. [proc-doc]\n\nA process truncating another process's dirty file may gain cancelled_write_bytes without a matching write_bytes charge of its own. Hesela observed this in a temporary-file experiment with an fsync-before-truncation control, recording all counter snapshots and source provenance. [proc-man] [hesela-observation]\n\nReaping can move a child's I/O contribution into its parent's process counters. In Hesela's single-parent experiment, the parent gained no wchar or write_bytes after WNOWAIT, then gained the child's 1 or 4 MiB at waitpid reaping while its individual-task view stayed unchanged. Keeping the child's historical total and adding the inclusive parent total counts that contribution twice. WNOWAIT observes termination without consuming the status; stopped-child waits also did not transfer the contribution. [wait-man] [linux-exit] [hesela-observation]",
  "status": "shipping",
  "advantages": [],
  "limitations": [
    {
      "text": "A per-process write-minus-cancellation difference can be negative and is not a physical-device traffic counter.",
      "citationIds": [
        "proc-doc",
        "proc-man"
      ]
    },
    {
      "text": "Process totals include waited-for children; a parent's increase at reaping need not mean a new write. The leader's task-only path is not a complete substitute for multithreaded process accounting.",
      "citationIds": [
        "proc-man",
        "linux-proc",
        "hesela-observation"
      ]
    }
  ],
  "related": [
    "page-cache",
    "memory-mapped-file",
    "file-truncation",
    "write-amplification"
  ],
  "supersedes": [],
  "supersededBy": [],
  "firstSeen": null,
  "lastSeen": null,
  "updated": "2026-10-18",
  "citations": [
    {
      "id": "proc-doc",
      "title": "Linux kernel documentation: /proc/PID/io accounting, section 3.3",
      "url": "https://docs.kernel.org/filesystems/proc.html",
      "accessed": "2026-10-18"
    },
    {
      "id": "proc-man",
      "title": "Linux man-pages 6.19: proc_pid_io(5)",
      "url": "https://man7.org/linux/man-pages/man5/proc_pid_io.5.html",
      "accessed": "2026-10-18"
    },
    {
      "id": "hesela-observation",
      "title": "Hesela: Linux process I/O accounting observations and reproducible harness",
      "url": "https://hesela.com/analyses/linux-process-io-accounting/",
      "accessed": "2026-10-18"
    },
    {
      "id": "wait-man",
      "title": "Linux man-pages: wait(2), waitid WNOWAIT semantics",
      "url": "https://man7.org/linux/man-pages/man2/wait.2.html",
      "accessed": "2026-10-18"
    },
    {
      "id": "linux-exit",
      "title": "Linux v6.8 kernel/exit.c: wait_task_zombie and child I/O accumulation",
      "url": "https://github.com/torvalds/linux/blob/v6.8/kernel/exit.c#L1010-L1091",
      "accessed": "2026-10-18"
    },
    {
      "id": "linux-proc",
      "title": "Linux v6.8 fs/proc/base.c: process and task I/O accounting views",
      "url": "https://github.com/torvalds/linux/blob/v6.8/fs/proc/base.c#L2803-L2867",
      "accessed": "2026-10-18"
    }
  ]
}
