Learn Tools to Inspect the Linux Process Memory Map – Free Linux Device Driver Course

FREE LINUX KERNEL PROGRAMMING COURSE

Tools to Inspect the Linux Process Memory Map

Go beyond /proc/PID/maps with pmap, smem, and procmap. Learn what each tool shows, when to use it, and how to interpret physical memory metrics like RSS, PSS, and USS.

Part 2
of 2
~20 min
read time
Hands-on
practical

From Raw Data to Useful Insights

In Part 1 we learned how to read the raw /proc/PID/maps file and understand what every field means. That raw output is powerful but dense. In practice, engineers use higher-level tools that parse this data and present it in a more useful way. This tutorial covers the three most important ones: pmap, smem, and a third tool that visualises both kernel and user VAS together.

pmap — the standard memory map viewer smem — who is using the most physical RAM? RSS vs PSS vs USS explained /proc/PID/smaps in detail Reading both user and kernel VAS at once

The Detailed View: /proc/PID/smaps

You already know that /proc/PID/maps gives you one line per memory segment. Linux also provides a much more detailed version at /proc/PID/smaps. For each segment in the maps file, smaps adds a block of detailed physical memory statistics.

Try running this in your terminal to see it for yourself:

$ cat /proc/self/smaps

You will see blocks like this for every segment:

7f3a2c000000-7f3a2c400000 rw-p 00000000 00:00 0
Size:               4096 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                 100 kB
Pss:                  50 kB
Shared_Clean:         80 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:        20 kB
Referenced:          100 kB
Anonymous:           100 kB
...

The man proc page documents every field. The key ones you need to understand are RSS, PSS, and USS — three ways of measuring how much physical RAM a mapping is actually using.

Understanding RSS, PSS, and USS

When a file like libc.so is loaded into memory, it is often shared between dozens of processes. If you simply add up “how many bytes is this process using”, you get an inflated number because the shared pages are counted multiple times. RSS, PSS, and USS are three progressively more accurate ways of answering “how much RAM is this process actually consuming?”

How RSS, PSS, and USS Measure Memory — A Visual Example

Scenario: libc.so (400 KB) is shared by 4 processes. Process A also has 100 KB of private anonymous memory.

libc.so pages (shared)
100
KB
100
KB
100
KB
100
KB
= 400 KB total
+
Private pages (Process A only)
100
KB
= 100 KB private
Metric Full Name Value for Process A How It Is Calculated
RSS Resident Set Size 500 KB All physical pages currently in RAM for this process, counting shared pages in full. Overestimates shared cost.
PSS Proportional Set Size 200 KB Private pages + (shared pages ÷ number of sharers). 100 KB private + (400 KB ÷ 4) = 200 KB. Fairer measure.
USS Unique Set Size 100 KB Only private pages. Memory that would be freed if this process was killed. Most conservative measure.
✅ Which Metric to Use?

RSS is what you see in top and ps. It is quick but overestimates. PSS is the most useful metric for capacity planning — it fairly distributes shared costs. USS tells you the real cleanup impact if a process is killed. Use PSS for comparing processes, USS for leak detection.

pmap — Your Primary Memory Map Viewer

pmap is a standard Linux utility that presents the process memory map in a clean, readable format. It reads from /proc/PID/maps (and optionally /proc/PID/smaps) and formats the output as a table with column headers, making it much easier to scan than the raw file.

Basic usage:

# Show memory map for process with a specific PID
$ pmap <PID>

# Show extended information (adds RSS per mapping)
$ pmap -x <PID>

# Show the most detailed output available
$ pmap -XX <PID>

The -x flag adds a column showing the RSS for each individual mapping — very useful for tracking which shared library is consuming the most physical memory. The -XX flag dumps everything that the kernel provides in /proc/PID/smaps, which is the maximum detail level you can get from a standard tool.

What pmap -x Shows — Column Breakdown
Column Example What It Tells You
Address 0000555d83b65000 Start of the virtual address region
Kbytes 12 Size of the virtual region in kilobytes
RSS 8 Physical RAM pages actually loaded (in KB)
Dirty 0 Pages modified since loading (need writeback)
Mode r-x– Permissions for this mapping
Mapping /bin/cat Source file or label for this mapping
Interpreting the pmap Summary Line
total 11932KB 1228KB 132KB
11932 KB
Total virtual address space reserved. Not all of this is in RAM yet — pages are loaded on demand.
1228 KB
RSS — physical RAM pages actually resident for this process right now.
132 KB
Dirty pages — modified in RAM but not yet written back to disk or swap.

A common beginner mistake is to assume that “virtual size = RAM used”. As the diagram shows, the virtual reservation can be much larger than the physical footprint. Linux uses demand paging — it only loads pages into physical RAM when they are actually accessed.

smem — Finding the Actual Memory Hog

smem solves a very specific but common problem: which process on my system is actually consuming the most physical memory? If you use RSS for this comparison, shared libraries count multiple times and the answer is misleading. smem uses PSS and USS, which give you a much more honest picture.

Unlike pmap, which focuses on the segments of a single process, smem works across all processes simultaneously and answers the system-wide question.

pmap vs smem — Two Different Questions
🔍 pmap

Question answered: What are all the memory segments of this specific process and how large is each one?

Use when: debugging a single process, finding which library takes up space

📊 smem

Question answered: Which process across the entire system is consuming the most real physical RAM?

Use when: investigating memory pressure, finding resource hogs, capacity planning

Install and run smem:

# Install on Debian/Ubuntu/Raspberry Pi OS
$ sudo apt install smem

# Show all processes sorted by PSS (most fair comparison)
$ smem --sort pss

# Show only the top 10 memory consumers
$ smem --sort pss | tail -10

# Output columns: PID, User, Command, Swap, USS, PSS, RSS
How smem Computes Memory per Process
RSS
All resident pages counted fully (includes shared pages × number of sharers)
PSS
Shared ÷ sharers + Private
USS
Private only

Bar length represents relative size. RSS is always the largest, USS the smallest.

⚠ Important Limitation of smem

smem reports on physical memory (pages in RAM). It does not directly show you the virtual address layout of a process the way pmap does. Think of them as complementary tools: use pmap for virtual layout, smem for physical footprint.

Visualising Both User and Kernel VAS

So far, all the tools we have discussed focus on the user-space half of the virtual address space. But every process actually has two halves: user space (where your application code and libraries live) and kernel space (where the kernel image, kernel stacks, module memory, and direct-mapped RAM live).

pmap and smem only show you the user-space half. To see both halves together for any given process, you can use extended utilities or read /proc/PID/smaps alongside kernel-specific pseudo-files. Some debugging-oriented tools (available as open-source projects on GitHub) provide a vertically tiled visualisation of the complete VAS — both user and kernel — in a single view ordered by descending segment size.

The Complete Virtual Address Space — Both Halves
0xFFFF_FFFF_FFFF_FFFF
🛡 Kernel Virtual Address Space
Kernel code + static data r-x
Direct-mapped RAM (physmem) rw-
vmalloc / module memory rw-
Kernel stacks, percpu data rw-
0x0000_8000_0000_0000 ← Kernel/User boundary
👤 User Virtual Address Space (UVA)
[stack] — user stack rw-p
[vdso] [vvar] — fast syscall r–p
Shared libraries (.so files) r-xp
[heap] — dynamic allocations rw-p
/bin/yourprogram — .text .data .bss r-xp
0x0000_0000_0000_0000

The tools you use in practice (pmap, smem, /proc/PID/maps) all show you the bottom half of this picture — the user VAS. Understanding that there is an equally important kernel half — and that the kernel is mapped into every process’s address space (but inaccessible from user mode) — is key to understanding how system calls work and why mode switching has a cost.

Practical Workflow: Diagnosing Memory Issues

Now that you understand the tools, here is a practical decision flow for common memory investigation tasks:

Which Tool to Use — Decision Guide
Question
Which process is using the most RAM right now?
→ Use smem --sort pss — it gives you a fair comparison across all processes
Question
What libraries is process X loading, and how big is each?
→ Use pmap -x <PID> — see each mapping with RSS
Question
Is this process leaking memory over time?
→ Watch smem USS over time — if USS keeps growing, there is a leak
Question
How is a specific segment being used in detail?
→ Read /proc/PID/smaps directly — richest data source
Question
Is a mapping file-backed or anonymous?
→ Check inode field in /proc/PID/maps — non-zero means file-backed
💻 Hands-On Exercise

Try this on your Linux machine (any modern distro works):

# Step 1: Open a terminal and start a background sleep process
$ sleep 600 &
[1] 12345          # note the PID (yours will be different)

# Step 2: Look at its raw memory map
$ cat /proc/12345/maps

# Step 3: Use pmap for a cleaner view
$ pmap -x 12345

# Step 4: See detailed per-segment stats
$ cat /proc/12345/smaps | head -60

# Step 5: Check how the sleep binary inode matches on disk
$ ls -i $(which sleep)

# Step 6: Clean up
$ kill %1

For step 5, compare the inode number from ls -i against what you see in the /proc/PID/maps output for the /usr/bin/sleep line. They will match — confirming how the VFS inode ties the VAS entry to the file on disk.

Interview Questions on This Topic

These types of questions appear frequently in embedded Linux and kernel engineering interviews at companies like Texas Instruments, Qualcomm, and STMicroelectronics:

Q: What is the difference between RSS and PSS, and when would you use each?
A: RSS counts all resident pages including shared ones at full cost, leading to overcounting. PSS divides shared pages proportionally among the processes that share them. Use RSS for a quick check; use PSS when fairly comparing memory usage across multiple processes or when doing system-level capacity planning.
Q: What does an inode value of 0 mean in /proc/PID/maps?
A: An inode of 0 means the mapping is anonymous — it has no backing file on disk. Examples include the process stack, the heap, and any memory region created with mmap(MAP_ANONYMOUS). These regions are backed only by physical RAM (and potentially swap), not by a file.
Q: What is vDSO and why does it exist?
A: vDSO (Virtual Dynamic Shared Object) is a small shared library that the kernel maps into every process at startup. It contains implementations of a small number of system calls (like gettimeofday and clock_gettime) that only need to read kernel data. By mapping this code into user space, the kernel avoids the overhead of a full mode switch for these frequent calls. Unlike the older vsyscall mechanism, vDSO maps at a randomised address and is fully ASLR-compatible.
Q: How can you tell from /proc/PID/maps if an address is a user VAS or kernel VAS address on x86-64?
A: On x86-64, user virtual addresses (UVAs) have their top 16 bits all set to zero (the address looks like 0x0000_xxxx_xxxx_xxxx). Kernel virtual addresses have their top 16 bits all set to one (the address looks like 0xffff_xxxx_xxxx_xxxx). The vsyscall page is a special case — it is a kernel page mapped at a fixed high address, which is why its top bits are set.

🎯 Key Takeaways from Part 2

/proc/PID/smaps = rich per-segment data pmap = formatted single-process view smem = cross-process fair comparison RSS overestimates due to shared pages PSS = fairest measure for comparison USS = how much frees if process dies Virtual size ≠ physical RAM used pmap + smem are complementary tools

Continue Your Free Linux Kernel Journey

EmbeddedPathashala offers completely free courses on Linux kernel programming, Linux device drivers, and Bluetooth/BLE development. No fees, no sign-ups required.

Browse All Free Courses

Leave a Reply

Your email address will not be published. Required fields are marked *