Memory Management with pmap Process ID in linux

Hacking Truth


Memory Management with pmap Process ID in linux


Finding out how much RAM a Linux process uses isn’t a simple matter—especially when shared memory needs to be considered. Thankfully, the pmap command helps you make sense of it all. Memory Management with pmap Process ID in linux


Memory Management

In Ram we have limited no of size, every process which gets executed goes in RAM, there is allocation & deallocation done by OS. In RAM after this process is done.

Memory Mapping

Memory mapping is the translation between the logical address space and the physical memory.

The objectives of memory mapping are:

  1. To translate from logical to physical address.
  2. To aid in memory protection.
  3. To enable better management of memory resources.

RAM on Demand

The mapping table and the concept of “RAM on demand” open up the possibility of shared memory. The kernel will try to avoid loading the same thing into memory more than once. For example, it will load a shared library into memory once and map it to the different processes that need to use it. Each of the processes will have its own unique address for the shared library, but they’ll all point to the same actual location.

If the shared region of memory is writable, the kernel uses a scheme called copy-on-write. If one process writes to the shared memory and the other processes sharing that memory are not supposed to see the changes, a copy of the shared memory is created at the point of the write request.

The pmap Utility

The kernel exposes a lot of what it is doing with RAM through two pseudo-files in the “/proc” system information pseudo-filesystem. There are two files per process, named for the process ID or PID of each process: “/proc/maps” and “/proc//smaps.”

The pmap tool reads information from these files and displays the results in the terminal window. It’ll be obvious that we need to provide the PID of the process we’re interested in whenever we usepmap.

PMAP(1)                                                                              User Commands                                                                              PMAP(1)                                                                                                                                                                                                 
       pmap - report memory map of a process                                                                                                                                                                                                                                                                                                                                            
       pmap [options] pid [...]                                                                                                                                                                                                                                                                                                                                                         
       The pmap command reports the memory map of a process or processes.                                                                                                                                                                                                                                                                                                               
       -x, --extended                                                                                                                                                                                                                                                                                                                                                                   
              Show the extended format.                                                                                                                                                                                                                                                                                                                                                 
       -d, --device
              Show the device format.

       -q, --quiet
              Do not display some header or footer lines.

       -A, --range low,high
              Limit results to the given range to low and high address range.  Notice that the low and high arguments are single string separated with comma.

       -X     Show even more details than the -x option. WARNING: format changes according to /proc/PID/smaps

       -XX    Show everything the kernel provides

       -p, --show-path
              Show full path to files in the mapping column

       -c, --read-rc
              Read the default configuration

       -C, --read-rc-from file
              Read the configuration from file

       -n, --create-rc
              Create new default configuration

       -N, --create-rc-to file
              Create new configuration to file

       -h, --help
              Display help text and exit.

       -V, --version
              Display version information and exit.

              0      Success.
              1      Failure.
              42     Did not find all processes asked for.

       ps(1), pgrep(1)

       No standards apply, but pmap looks an awful lot like a SunOS command.

       Please send bug reports to ⟨⟩

procps-ng                                                                              2020-06-04                                                                               PMAP(1)

Finding the Process ID

There are several ways to find the PID of a process. Here’s the source code for a trivial program we’ll use in our examples. It is written in C. All it does is print a message to the terminal window and wait for the user to hit the “Enter” key.

#include <stdio.h>

int main(int argc, char *argv[])
  printf("Thank you for visiting Hacking Truth.");
} // end of main

The program was compiled to an executable called pm using the gcc compiler:

gcc -o pm pm.c

Because the program will wait for the user to hit “Enter”, it’ll stay running for as long as we like.


Memory Management with pmap Process ID in linux

The program launches, prints the message, and waits for the keystroke. We can now search for its PID. The ps command lists running processes. The -e (show all processes) option makes ps list every process. We’ll pipe the output through grep and filter out entries that have “pm” in their name.

ps -e | grep pm

Memory Management with pmap Process ID in linux

This lists all of the entries with “pm” anywhere in their names.

We can be more specific using the pidof command. We give pidof the name of the process we’re interested in on the command line, and it tries to find a match. If a match is found, pidof prints the PID of the matching process.

pidof pm

└─$ pidof pm

The pidof method is neater when you know the name of the process, but the ps method will work even if only know part of the process name.
Using pmap

With our test program running, and once we’ve identified its PID, we can use pmap like this:

pmap 58456

└─$ pmap 58456           
58456:   ./pm

The memory mappings for the process are listed for us.

40919: ./pm
000056059f06c000      4K r---- pm
000056059f06d000      4K r-x-- pm
000056059f06e000      4K r---- pm
000056059f06f000      4K r---- pm
000056059f070000      4K rw--- pm
000056059fc39000    132K rw--- [ anon ]
00007f97a3edb000      8K rw--- [ anon ]
00007f97a3edd000    160K r----
00007f97a3f05000   1616K r-x--
00007f97a4099000    352K r----
00007f97a40f1000      4K -----
00007f97a40f2000     16K r----
00007f97a40f6000      8K rw---
00007f97a40f8000     60K rw--- [ anon ]
00007f97a4116000      4K r----
00007f97a4117000    160K r-x--
00007f97a413f000     40K r----
00007f97a4149000      8K r----
00007f97a414b000      8K rw---
00007ffca0e7e000    132K rw--- [ stack ]
00007ffca0fe1000     16K r---- [ anon ]
00007ffca0fe5000      8K r-x-- [ anon ]
ffffffffff600000      4K --x-- [ anon ]
total              2756K

The first line is the process name and its PID. Each of the other lines shows a mapped memory address, and the amount of memory at that address, expressed in kilobytes. The next five characters of each line are called virtual memory permissions. Valid permissions are:

  • r: The mapped memory can be read by the process.
  • w: The mapped memory can be written by the process.
  • x: The process can execute any instructions contained in the mapped memory.
  • s: The mapped memory is shared, and changes made to the shared memory are visible to all of the processes sharing the memory.
  • R: There is no reservation for swap space for this mapped memory.


The final information on each line is the name of the source of the mapping. This can be a process name, library name, or a system name such as stack or heap.


The Extended Display

The -x (extended) option provides two extra columns.

pmap -x 58456

└─$ pmap -x 59078
59078:   /bin/zsh
Address           Kbytes     RSS   Dirty Mode  Mapping
0000556453c15000      92      92       0 r---- zsh
0000556453c2c000     596     596       0 r-x-- zsh
0000556453cc1000     136      64       0 r---- zsh
0000556453ce4000       8       8       8 r---- zsh
0000556453ce6000      24      24      24 rw--- zsh
0000556453cec000      80      36      36 rw---   [ anon ]
0000556454e5c000    1836    1796    1796 rw---   [ anon ]
00007f92590fd000       4       4       0 r----
00007f92590fe000       4       4       0 r-x--
00007f92590ff000       4       4       0 r----
00007f9259100000       4       4       4 r----
00007f9259101000       4       4       4 rw---
00007f9259102000     100      44       0 r--s- Misc.zwc
00007f925911b000     144      44       0 r--s- Base.zwc
00007f925913f000       4       4       0 r----
00007f9259140000       8       8       0 r-x--
00007f9259142000       4       4       0 r----
00007f9259143000       4       4       4 r----
00007f9259144000       4       4       4 rw---
00007f9259168000       4       4       0 r----
00007f9259169000       4       4       0 r-x--
00007f925916a000       4       4       0 r----
00007f925916b000       4       4       4 r----
00007f925916c000       4       4       4 rw---
00007f9259171000      96      60       0 r--s- Completion.zwc
00007f9259189000      12      12       0 r----
00007f925918c000      20      16       0 r-x--
00007f9259191000       8       8       0 r----
00007f9259193000       4       0       0 -----
00007f9259194000       4       4       4 r----
00007f9259195000       4       4       4 rw---
00007f9259196000       8       8       0 r----
00007f9259198000      20      20       0 r-x--
00007f925919d000       4       4       0 r----
00007f925919e000       4       0       0 -----
00007f925919f000       4       4       4 r----
00007f92591a0000       4       4       4 rw---
00007f92591a1000      32      32       0 r----
00007f92591a9000     104      72       0 r-x--
00007f92591c3000      12      12       0 r----
00007f92591c6000       8       8       8 r----
00007f92591c8000       4       4       4 rw---
00007f92591c9000      92      92       0 r----
00007f92591e0000     168     168       0 r-x--
00007f925920a000      40      40       0 r----
00007f9259214000       8       8       8 r----
00007f9259216000      28      28      28 rw---
00007f925921d000       4       4       4 rw---   [ anon ]
00007f9259222000      12      12       0 r----
00007f9259225000      24      24       0 r-x--
00007f925922b000       8       8       0 r----
00007f925922d000       4       4       4 r----
00007f925922e000       4       4       4 rw---
00007f925922f000      24       0       0 rw---   [ anon ]
00007f9259235000    2972     540       0 r---- locale-archive
00007f925951c000       8       8       8 rw---   [ anon ]
00007f925951e000     152     152       0 r----
00007f9259544000    1312    1200       0 r-x--
00007f925968c000     300     208       0 r----
00007f92596d7000       4       0       0 -----
00007f92596d8000      12      12      12 r----
00007f92596db000      12      12      12 rw---
00007f92596de000      36      20      20 rw---   [ anon ]
00007f92596e7000      60      60       0 r----
00007f92596f6000     616     296       0 r-x--
00007f9259790000     608       0       0 r----
00007f9259828000       4       4       4 r----
00007f9259829000       4       4       4 rw---
00007f925982a000      56      56       0 r----
00007f9259838000      64      64       0 r-x--
00007f9259848000      56      56       0 r----
00007f9259856000      16      16      16 r----
00007f925985a000       4       4       4 rw---
00007f925985b000       8       8       0 r----
00007f925985d000       8       8       0 r-x--
00007f925985f000       4       0       0 r----
00007f9259860000       4       4       4 r----
00007f9259861000       4       4       4 rw---
00007f9259862000      12      12       0 r----
00007f9259865000      16      16       0 r-x--
00007f9259869000       8       0       0 r----
00007f925986b000       4       4       4 r----
00007f925986c000       4       4       4 rw---
00007f925986d000       8       8       8 rw---   [ anon ]
00007f9259872000       4       4       0 r----
00007f9259873000       4       4       0 r-x--
00007f9259874000       4       4       0 r----
00007f9259875000       4       4       4 r----
00007f9259876000       4       4       4 rw---
00007f925987b000      28      28       0 r--s- gconv-modules.cache
00007f9259882000      16      16      16 rw---   [ anon ]
00007f9259886000       4       4       0 r----
00007f9259887000     144     144       0 r-x--
00007f92598ab000      40      40       0 r----
00007f92598b5000       8       8       8 r----
00007f92598b7000       8       8       8 rw---
00007ffceadbc000     164     164     164 rw---   [ stack ]
00007ffceadf5000      16       0       0 r----   [ anon ]
00007ffceadf9000       8       4       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB           10680    6648    2272

The columns are given titles. We have already seen the “Address”, “Kbytes”, “Mode”, and “Mapping” columns. The new columns are called “RSS” and “Dirty.”

  • RSS: This is the resident set size. That is, the amount of memory that is currently in RAM, and not swapped out.
  • Dirty: “Dirty” memory has been changed since the process—and the mapping—started.

Show Me Everything

The -X (even more than extended) adds additional columns to the output. Note the uppercase “X.” Another option called -XX (even more than -X ) shows you everything pmap can get from the kernel. As -X is a subset of -XX, we’ll describe the output from -XX .

pmap -XX 58456

└─$ pmap -XX 59078
59078:   /bin/zsh
     Address Perm   Offset Device   Inode  Size KernelPageSize MMUPageSize  Rss  Pss Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous LazyFree AnonHugePages ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible                 VmFlags Mapping
556453c15000 r--p 00000000  08:08 6302183    92              4           4   92   30           92            0             0             0         92         0        0             0              0             0              0               0    0       0      0           0       rd mr mw me dw sd zsh
556453c2c000 r-xp 00017000  08:08 6302183   596              4           4  596  198          596            0             0             0        596         0        0             0              0             0              0               0    0       0      0           0    rd ex mr mw me dw sd zsh
556453cc1000 r--p 000ac000  08:08 6302183   136              4           4   64   21           64            0             0             0         64         0        0             0              0             0              0               0    0       0      0           0       rd mr mw me dw sd zsh
556453ce4000 r--p 000ce000  08:08 6302183     8              4           4    8    8            0            0             0             8          8         8        0             0              0             0              0               0    0       0      0           0    rd mr mw me dw ac sd zsh
556453ce6000 rw-p 000d0000  08:08 6302183    24              4           4   24   24            0            0             0            24         24        24        0             0              0             0              0               0    0       0      0           0 rd wr mr mw me dw ac sd zsh
556453cec000 rw-p 00000000  00:00       0    80              4           4   36   36            0            0             0            36         36        36        0             0              0             0              0               0    0       0      0           0    rd wr mr mw me ac sd 
556454e5c000 rw-p 00000000  00:00       0  1836              4           4 1800 1800            0            0             0          1800       1800      1800        0             0              0             0              0               0    0       0      0           0    rd wr mr mw me ac sd [heap]
7f92590fd000 r--p 00000000  08:08  265771     4              4           4    4    1            4            0             0             0          4         0        0             0              0             0              0               0    0       0      0           0          rd mr mw me sd

There’s a lot of information here. This is what the columns hold:

Address: The start address of this mapping. This uses virtual memory addressing.

Perm: The permissions of the memory.

Offset: If the memory is file-based, the offset of this mapping inside the file.
Device: The Linux device number, given in major and minor numbers. You can see the device numbers on your computer by running the lsblk command.

Inode: The inode of the file the mapping is associated with. For example, in our example, this could be the inode that holds information about the pm program.

Size: The size of the memory-mapped region.

KernelPageSize: The page size used by the kernel.

MMUPageSize: The page size used by the memory management unit.
Rss: This is the resident set size. That is, the amount of memory that is currently in RAM, and not swapped out.

Pss: This is the proportional share size. This is the private shared size added to the (shared size divided by the number of shares.)

Shared_Clean: The amount of memory shared with other processes that has not been altered since the mapping was created. Note that even if memory is shareable, if it hasn’t actually been shared it is still considered private memory.

Shared_Dirty: The amount of memory shared with other processes that has been altered since the mapping was created.

Private_Clean: The amount of private memory—not shared with other processes—that has not been altered since the mapping was created.

Private_Dirty: The amount of private memory that has been altered since the mapping was created.

Referenced: The amount of memory currently marked as referenced or accessed.

Anonymous: Memory that does not have a device to swap out to. That is, it isn’t file-backed.

LazyFree: Pages that have been flagged as MADV_FREE. These pages have been marked as available to be freed and reclaimed, even though they may have unwritten changes in them. However, if subsequent changes occur after the MADV_FREE has been set on the memory mapping, the MADV_FREE flag is removed and the pages will not be reclaimed until the changes are written.

AnonHugePages: These are non-file backed “huge” memory pages (larger than 4 KB).

ShmemPmdMapped: Shared memory associated with huge pages. They may also be used by filesystems that reside entirely in memory.

FilePmdMapped: The Page Middle Directory is one of the paging schemes available to the kernel. This is the number of file-backed pages pointed to by PMD entries.

Shared_Hugetlb: Translation Lookaside Tables, or TLBs, are memory caches used to optimize the time taken to access userspace memory locations. This figure is the amount of RAM used in TLBs that are associated with shared huge memory pages.

Private_Hugetlb: This figure is the amount of RAM used in TLBs that are associated with private huge memory pages.

Swap: The amount of swap being used.

SwapPss: The swap proportional share size. This is the amount of swap made up of swapped private memory pages added to the (shared size divided by the number of shares.)

Locked: Memory mappings can be locked to prevent the operating system from paging out heap or off-heap memory.

THPeligible: This is a flag indicating whether the mapping is eligible for allocating transparent huge pages. 1 means true, 0 means false. Transparent huge pages is a memory management system that reduces the overhead of TLB page lookups on computers with a large amount of RAM.

VmFlags: See the list of flags below.

Mapping: The name of the source of the mapping. This can be a process name, library name, or system names such as stack or heap.

The VmFlags—virtual memory flags—will be a subset of the following list.

    rd: Readable.
    wr: Writeable.
    ex: Executable.
    sh: Shared.
    mr: May read.
    mw: May write.
    me: May execute.
    ms: May share.
    gd: Stack segment grows down.
    pf: Pure page frame number range. Page frame numbers are a list of the physical memory pages.
    dw: Disabled write to the mapped file.
    lo: Pages are locked in memory.
    io: Memory-mapped I/O area.
    sr: Sequential read advise provided (by the madvise() function.)
    rr: Random read advise provided.
    dc: Do not copy this memory region if the process is forked.
    de: Do not expand this memory region on remapping.
    ac: Area is accountable.
    nr: Swap space is not reserved for the area.
    ht: Area uses huge TLB pages.
    sf: Synchronous page fault.
    ar: Architecture-specific flag.
    wf: Wipe this memory region if the process is forked.
    dd: Do not include this memory region in core dumps.
    sd: Soft dirty flag.
    mm: Mixed map area.
    hg: Huge page advise flag.
    nh: No huge page advise flag.
    mg: Mergeable advise flag.
    bt: ARM64 bias temperature instability guarded page.
    mt: ARM64 Memory tagging extension tags are enabled.
    um: Userfaultfd missing tracking.
    uw: Userfaultfd wr-protect tracking.

One final neat trick is that you can use pmap and the pidof commands together, combining the actions of finding the PID of the process and passing it to pmap into one command:

pmap $(pidof pm)

└─$ pmap $(pidof pm)      
58456:   ./pm
└─$                                                                                                                                                                                     1 ⨯

Post a Comment

* Please Don't Spam Here. All the Comments are Reviewed by Admin.
Post a Comment (0)
Our website uses cookies to enhance your experience. Learn More
Accept !