I am trying to understand memory mapping in Linux, and wrote below program for the same.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define MEM_SIZE 1*1024*1024*1024 // 1GB
#define PAGE_SIZE 4*1024
#define NO_OF_PAGES (MEM_SIZE)/(PAGE_SIZE)
// Global array of size 1 GB
int mem[MEM_SIZE/sizeof(int)] = {
0,1,2,
};
void *func(void *args)
{
while (1) {
for (int i=0; i<NO_OF_PAGES; i ) {
mem[(i*PAGE_SIZE)/sizeof(int)] = 1; // Update first 4-bytes of each page.
}
// All pages are updated.
fflush(stdout);
printf("."); // Each dot(.) represents update of all pages in global data.
}
return NULL;
}
int main() {
pthread_t t;
pthread_create(&t, NULL, func, NULL);
printf("A thread is continually updating all pages of global 1GB data. (pid : %d)\n", getpid());
pthread_join(t, NULL);
return 0;
}
It executes like this,
[ ] gcc test.c
[ ] ./a.out
A thread is continually updating all pages of global 1GB data. (pid : 4086)
.......................
Here, a thread is continually updating all pages of the global data used in this program. Hence, this process should consume ~1GB (MEM_SIZE) in memory.
But the process memory looks like below, (I can not see 1GB of data memory being used here).
[ ]# cat /proc/4086/maps
55eac3b7c000-55eac3b7d000 r--p 00000000 08:01 1197055 /root/testing/a.out
55eac3b7d000-55eac3b7e000 r-xp 00001000 08:01 1197055 /root/testing/a.out
55eac3b7e000-55eac3b7f000 r--p 00002000 08:01 1197055 /root/testing/a.out
55eac3b7f000-55eac3b80000 r--p 00002000 08:01 1197055 /root/testing/a.out
55eac3b80000-55eb03b81000 rw-p 00003000 08:01 1197055 /root/testing/a.out
55eb047b5000-55eb047d6000 rw-p 00000000 00:00 0 [heap]
7f19c791b000-7f19c791c000 ---p 00000000 00:00 0
7f19c791c000-7f19c811e000 rw-p 00000000 00:00 0
7f19c811e000-7f19c8140000 r--p 00000000 08:01 1969450 /usr/lib/libc.so.6
7f19c8140000-7f19c829b000 r-xp 00022000 08:01 1969450 /usr/lib/libc.so.6
7f19c829b000-7f19c82f2000 r--p 0017d000 08:01 1969450 /usr/lib/libc.so.6
7f19c82f2000-7f19c82f6000 r--p 001d4000 08:01 1969450 /usr/lib/libc.so.6
7f19c82f6000-7f19c82f8000 rw-p 001d8000 08:01 1969450 /usr/lib/libc.so.6
7f19c82f8000-7f19c8307000 rw-p 00000000 00:00 0
7f19c8311000-7f19c8312000 r--p 00000000 08:01 1969441 /usr/lib/ld-linux-x86-64.so.2
7f19c8312000-7f19c8338000 r-xp 00001000 08:01 1969441 /usr/lib/ld-linux-x86-64.so.2
7f19c8338000-7f19c8342000 r--p 00027000 08:01 1969441 /usr/lib/ld-linux-x86-64.so.2
7f19c8342000-7f19c8344000 r--p 00031000 08:01 1969441 /usr/lib/ld-linux-x86-64.so.2
7f19c8344000-7f19c8346000 rw-p 00033000 08:01 1969441 /usr/lib/ld-linux-x86-64.so.2
7ffe8b517000-7ffe8b538000 rw-p 00000000 00:00 0 [stack]
7ffe8b599000-7ffe8b59d000 r--p 00000000 00:00 0 [vvar]
7ffe8b59d000-7ffe8b59f000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
[ ]#
Though, meminfo reflects the consumption of ~1GB.
Before starting this program:
[ ]# cat /proc/meminfo | grep 'MemFree\|SwapFree'
MemFree: 6740324 kB
SwapFree: 0 kB
and after starting the program:
[ ]# cat /proc/meminfo | grep 'MemFree\|SwapFree'
MemFree: 5699312 kB
SwapFree: 0 kB
CodePudding user response:
In the map, we can see the following zones:
- 7f19c791b000-7f19c791c000 ---p 00000000 00:00 0 : Red zone to protect the stack of the thread = non RW 4KB long page (stack overflow detection)
- 7f19c791c000-7f19c811e000 rw-p 00000000 00:00 0 : Stack of the thread (it grows from high to low memory addresses)
- 55eac3b80000-55eb03b81000 rw-p 00003000 08:01 1197055 : the 1 GB memory space (mem[] table) 4KB
You could add to your program the display of the mem[] table address:
printf("A thread is continually updating all pages of global 1GB data (mem[]@%p). (pid : %d)\n", mem, getpid());
The size
command displays the size of the data segment which is ~1GB:
$ gcc test.c -l pthread
$ size a.out
text data bss dec hex filename
2571 1073742504 16 1073745091 40000cc3 a.out
Execution which shows mem[]'s address at: 0x562c48575020
$ ./a.out
A thread is continually updating all pages of global 1GB data (mem[]@0x562c48575020). (pid : 10029)
.............................................
Display of the map from another terminal where we can see the address of mem[] located in the zone 562c48575000-562c88576000:
$ cat /proc/`pidof a.out`/maps
562c48571000-562c48572000 r--p 00000000 08:05 9044419 /home/xxx/a.out
562c48572000-562c48573000 r-xp 00001000 08:05 9044419 /home/xxx/a.out
562c48573000-562c48574000 r--p 00002000 08:05 9044419 /home/xxx/a.out
562c48574000-562c48575000 r--p 00002000 08:05 9044419 /home/xxx/a.out
562c48575000-562c88576000 rw-p 00003000 08:05 9044419 /home/xxx/a.out
562c89668000-562c89689000 rw-p 00000000 00:00 0 [heap]
7f02946be000-7f02946bf000 ---p 00000000 00:00 0
7f02946bf000-7f0294ebf000 rw-p 00000000 00:00 0
7f0294ebf000-7f0294ee1000 r--p 00000000 08:05 6031519 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f0294ee1000-7f0295059000 r-xp 00022000 08:05 6031519 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f0295059000-7f02950a7000 r--p 0019a000 08:05 6031519 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f02950a7000-7f02950ab000 r--p 001e7000 08:05 6031519 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f02950ab000-7f02950ad000 rw-p 001eb000 08:05 6031519 /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f02950ad000-7f02950b1000 rw-p 00000000 00:00 0
7f02950b7000-7f02950bd000 r--p 00000000 08:05 6031549 /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7f02950bd000-7f02950ce000 r-xp 00006000 08:05 6031549 /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7f02950ce000-7f02950d4000 r--p 00017000 08:05 6031549 /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7f02950d4000-7f02950d5000 r--p 0001c000 08:05 6031549 /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7f02950d5000-7f02950d6000 rw-p 0001d000 08:05 6031549 /usr/lib/x86_64-linux-gnu/libpthread-2.31.so
7f02950d6000-7f02950da000 rw-p 00000000 00:00 0
7f02950fc000-7f02950ff000 rw-p 00000000 00:00 0
7f02950ff000-7f0295100000 r--p 00000000 08:05 6031511 /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f0295100000-7f0295123000 r-xp 00001000 08:05 6031511 /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f0295123000-7f029512b000 r--p 00024000 08:05 6031511 /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f029512c000-7f029512d000 r--p 0002c000 08:05 6031511 /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f029512d000-7f029512e000 rw-p 0002d000 08:05 6031511 /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f029512e000-7f029512f000 rw-p 00000000 00:00 0
7f0295131000-7f0295133000 rw-p 00000000 00:00 0
7ffcb340f000-7ffcb3430000 rw-p 00000000 00:00 0 [stack]
7ffcb35ff000-7ffcb3603000 r--p 00000000 00:00 0 [vvar]
7ffcb3603000-7ffcb3605000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]