Read Process Memory Pages Safely with /proc/pid/statm
Top shows a memory number you do not trust, and /proc/pid/statm is the compact, seven-field readout behind it. You will read those counters, convert page counts to bytes or MiB, and decide whether that is enough or whether you need a slower, more detailed interface.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a Linux shell and a process ID. The examples use the locally installed Linux man-pages 6.7 package; the counters are provided by the kernel, so values and permissions depend on the process and host you inspect.
1. Choose a process and check the file
Start with your own shell process. Reading /proc/self/statm is an ordinary, unprivileged operation and avoids guessing another user's process ID:
$ printf 'pid: %s\n' "$$"
pid: 24180
$ test -r /proc/self/statm && echo readable
readable
$ cat /proc/self/statm
1566 463 433 5 0 124 0
The numbers will differ. The file is a single line of seven space-separated values, measured in memory pages. A changing process can produce a different line on every read, so treat one read as one snapshot rather than a permanent property of the process.
Checkpoint: if cat reports that the file does not exist, the process may have exited or the PID may be stale. If access is denied for another process, check that you are inspecting the intended PID before considering elevated access. Do not use sudo merely to make an unexplained number appear.
2. Map the seven positions
The positions have fixed meanings. Here is what each of the seven fields in /proc/pid/statm means; the first three are the ones you will use in a quick memory check:
| Position | Name | Meaning |
|---|---|---|
| 1 | size | Total program size, matching VmSize in /proc/pid/status. |
| 2 | resident | Resident set size. The manpage marks this as inaccurate and relates it to VmRSS. |
| 3 | shared | Resident shared pages, meaning pages backed by a file. This is also marked as inaccurate. |
| 4 | text | Text, or code, pages. |
| 5 | lib | Library pages. This field has been unused since Linux 2.6 and is always zero. |
| 6 | data | Data plus stack pages. |
| 7 | dt | Dirty pages. This field has been unused since Linux 2.6 and is always zero. |
Do not label the second value as an exact physical-memory measurement. The kernel documentation and local manpage both describe RSS-related values as subject to a scalability optimisation. A short-lived process can also change between the time you obtain its PID and the time you open its file.
3. Convert pages without assuming the page size
These counters are pages, not kilobytes. Ask the running system for its page size, then convert the first three fields. This command reads the page size once and prints the values with clear labels:
$ page_size=$(getconf PAGESIZE)
$ read size resident shared _ < /proc/self/statm
$ awk -v p="$page_size" -v s="$size" -v r="$resident" -v h="$shared" \
'BEGIN {
printf "page size: %d bytes\n", p
printf "size: %d pages (%.2f MiB)\n", s, s*p/1048576
printf "resident: %d pages (%.2f MiB)\n", r, r*p/1048576
printf "shared: %d pages (%.2f MiB)\n", h, h*p/1048576
}'
page size: 4096 bytes
size: 1566 pages (6.12 MiB)
resident: 463 pages (1.81 MiB)
shared: 433 pages (1.69 MiB)
The displayed values are examples from one run. On a system with a different page size, the conversion changes accordingly. Keep the raw page counts when recording measurements; they are the values the interface actually supplies.
For a different process, replace self with a validated numeric PID:
$ pid=24180
$ case "$pid" in (''|*[!0-9]*) printf 'PID must be numeric\n' >&2; exit 2;; esac
$ cat "/proc/$pid/statm"
1566 463 433 5 0 124 0
The quoted path prevents shell metacharacters from becoming part of the file name. The numeric check does not prove that the PID belongs to the program you expect, so confirm that separately with ps -p "$pid" -o pid=,comm=.
4. Compare the quick view with status
The first three counters have corresponding fields in /proc/pid/status. This is useful when you want human-readable units and nearby process metadata:
$ pid=$$
$ grep -E '^(VmSize|VmRSS|RssFile|RssShmem):' "/proc/$pid/status"
VmSize: 6420 kB
VmRSS: 1884 kB
RssFile: 1692 kB
RssShmem: 0 kB
The exact numbers need not line up perfectly with a separate statm read because the process can change and the relevant RSS accounting is not an exact synchronised snapshot. Use the files to answer different questions: statm is compact and easy to parse, while status gives named fields in a form that is easier to inspect.
5. Escalate to smaps when precision matters
Do not build an alert that treats resident or shared as exact accounting without allowing for their documented inaccuracy. If you need a detailed and more accurate inspection, read /proc/pid/smaps or /proc/pid/smaps_rollup instead:
$ pid=$$
$ test -r "/proc/$pid/smaps_rollup" && grep -E '^(Rss|Pss|Private_|Shared_).*:' "/proc/$pid/smaps_rollup"
Rss: 1884 kB
Pss: 1012 kB
Shared_Clean: 1692 kB
Shared_Dirty: 0 kB
Private_Clean: 128 kB
Private_Dirty: 64 kB
Your kernel may expose a different set of fields, and the values will vary. The trade-off is explicit: smaps and smaps_rollup are slower, but provide detailed information. Use them for a diagnostic snapshot, not in a tight polling loop without measuring the cost.
If smaps_rollup is absent, check smaps. If both are unavailable or unreadable, keep the limitation visible in your monitoring or report rather than silently substituting an inaccurate number. Access to another user's process can also be restricted by the host's proc settings and permissions.
6. Avoid the common traps
- Ignore the seventh field. The local manpage says it is unused and always zero, so it is not useful dirty-page accounting.
- Do not assume 4096-byte pages. Divide by the page size you actually measured, not by 1024.
- A zero fifth field means nothing. That field is obsolete; it is always zero on current Linux systems, libraries or not.
- Do not sample a dead PID forever. Processes exit and PIDs get reused, so reacquire and verify identity after a failed read.
- Change nothing to get these numbers. The workflow is read-only and needs no elevated privileges for your own process.
Done means
- Read the seven counters. You can read a validated PID's page counters from
/proc/pid/statm. - Converted with the real page size. You identify each position and convert page counts using the host's actual page size, not an assumed 4096.
- Trusted resident and shared the right amount. You treat them as approximate quick checks, not exact accounting.
- Know when to escalate. You reach for
statusfor named fields andsmapsorsmaps_rollupwhen detailed accuracy justifies the extra cost.