Home / Alt manpages / proc_pid_io(5)

  • proc_pid_io(5)
  • File format
  • linux

Read Per-Process I/O Counters from /proc/pid/io

You will read a Linux process's cumulative I/O counters, distinguish application-visible traffic from storage-layer traffic, and take a repeatable sample without changing the process. The examples use the installed proc_pid_io(5) page from Linux man-pages 6.7, package version 6.7-2. Allow about ten minutes. You need a shell and a process ID that still exists.

This is observation only. The commands do not restart services, alter files or require sudo when you inspect your own process. Access to another user's process can be denied by the kernel's ptrace access check, so elevated privileges are not a universal workaround and should not be your first response.

1. Choose a live process

Start with the shell running your commands. $$ is the shell's process ID in a normal POSIX shell. Check that the procfs file exists before reading it:

$ pid=$$
$ printf 'checking PID %s\n' "$pid"
checking PID 12345
$ test -r "/proc/$pid/io" && echo readable
readable

The number will differ on your machine. Do not copy the displayed PID literally. A PID can be reused after a process exits, so resolve it immediately before collecting a sample rather than keeping an old number in a script or notebook.

Checkpoint

You have a live PID and /proc/$pid/io is readable. If the test fails, choose a process you own or stop and check whether procfs is mounted. Do not make a service change merely to obtain statistics.

2. Read the seven counters

Read the file as one small, labelled report:

$ cat "/proc/$pid/io"
rchar: 2153311
wchar: 7385
syscr: 139
syscw: 10
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0

The values above are an example shape, not a promise about your process. The file reports seven cumulative counters: rchar and wchar count bytes returned by successful read-like and write-like system calls; syscr and syscw count the corresponding file-read and file-write calls. The syscall counters include the read and write families, sendfile(2), copy_file_range(2), and the documented Btrfs encoded I/O ioctls.

read_bytes counts bytes really fetched from the storage layer, and write_bytes counts bytes really sent there. Those figures are useful when asking whether storage was involved, but they are not interchangeable with the bytes an application requested. A cache hit can increase rchar without increasing read_bytes. Buffered writes can make the two write views occur at different times.

3. Compare a pair of samples

The counters are normally useful as deltas, not as absolute totals. Take two readings around the workload you care about:

$ pid=$$
$ before=$(awk '$1 == "rchar:" {print $2}' "/proc/$pid/io")
$ printf 'sample text\n' > /dev/null
$ after=$(awk '$1 == "rchar:" {print $2}' "/proc/$pid/io")
$ printf 'rchar delta: %s bytes\n' "$((after - before))"
rchar delta: 13 bytes

The exact delta depends on the shell and command sequence, so treat this as a method demonstration. The first sample must be captured before the workload, and both reads must refer to the same PID. For a long-running service, record a timestamp with each sample and calculate the change over a fixed interval. A rate is your calculation, not a field supplied by procfs.

Do not assume a zero storage counter means the program did no work. The data may have been served from cache, the process may have written through a different mechanism, or filesystem accounting may not expose the detail you expected. Look at all related fields and the workload's own logs before drawing a conclusion.

4. Account for children and cancelled writes

The manpage describes these statistics as covering the process and its waited-for children. That makes the file useful for some command wrappers, but it also means a parent process's totals may include work performed by children it has waited for. If you need per-process attribution, sample the worker PID itself and keep the parent and child PIDs separate.

cancelled_write_bytes records writeback that was later saved by truncation. For example, data written to a regular file and then removed before writeback can remain in the write accounting while the kernel avoids sending it to storage. This value applies to I/O already counted in write_bytes, and the effective storage write delta can therefore look negative. That is an accounting result, not evidence that the disk returned bytes to the process.

5. Handle permissions and unstable reads

Access to /proc/<pid>/io is governed by the ptrace PTRACE_MODE_READ_FSCREDS check. A permission error for another user's process is expected security behaviour. Confirm the target first:

$ ps -p "$pid" -o pid=,comm=
12345 bash
$ cat "/proc/$pid/io"
cat: /proc/12345/io: Permission denied

Use a process you are allowed to inspect, or follow your organisation's approved monitoring path. Avoid broad permission changes and avoid putting sensitive process data into world-readable logs.

The counters are not atomic. On systems where 64-bit operations can tear, a read concurrent with an update can produce an incorrect intermediate value. For trend work, take repeated samples and treat an isolated implausible jump as suspect. Do not present one read as a precise transaction boundary.

Done means

  • You selected a live PID and checked access to its procfs I/O file.
  • You can explain the difference between logical bytes, syscall counts and storage-layer bytes.
  • You calculated changes from two samples of the same process instead of treating totals as rates.
  • You accounted for waited-for children, cache effects and cancelled writes.
  • You kept the inspection read-only and treated permission errors as an access boundary.