I'm trying to understand "how memory works". As far as I understand the OS (Linux in my case) when calling mmap
to create MAP_ANONYMOUS
mapping it creates:
mmap()
creates a new mapping in the virtual address space of the calling process
As far as I know virtyal address space of a process may exceed tge actual physical memory available.
Also as far as I know the actual mapping to a physical memory occurs when CPU
triggers page fault when it tries to access to a memory page that is not in page table yet.
OS catches the page fault and creates an entry in a page directory.
What should happen if I mmap
ed some anonymous memory (but did not touch any of the pages), then other processess exhausted all the physical memory and then I try to use one of the pages mmap
ed (I have swap disabled)?
CPU should trigger page fault and then try to create an entry in a page direcrory. But since no physical memory left it will not be able to do so...
To use mmap (MAP_ANONYMOUS) or malloc changes nothing in your case, if you dont have enough free memory mmap returns MAP_FAILED
and malloc returns NULL
If I use that program :
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char ** argv)
{
int n = atoi(argv[1]);
void * m;
if (argc == 1) {
m = mmap(NULL, n*1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (m == MAP_FAILED) {
puts("ko");
return 0;
}
}
else {
m = malloc(n*1024*1024);
if (m == 0) {
puts("ko");
return 0;
}
}
puts("ok");
getchar();
char * p = (char *) m;
char * sup = p + n*1024*1024;
while (p < sup) {
*p = 0;
p += 512;
}
puts("done");
getchar();
return 0;
}
I am on a raspberrypi with 1Gb of memory and a swap of 100Mo, the memory is already used by chromium because I am on SO
proc/meminfo
gives :
MemTotal: 949448 kB
MemFree: 295008 kB
MemAvailable: 633560 kB
Buffers: 39296 kB
Cached: 360372 kB
SwapCached: 0 kB
Active: 350416 kB
Inactive: 260960 kB
Active(anon): 191976 kB
Inactive(anon): 41908 kB
Active(file): 158440 kB
Inactive(file): 219052 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 102396 kB
SwapFree: 102396 kB
Dirty: 352 kB
Writeback: 0 kB
AnonPages: 211704 kB
Mapped: 215924 kB
Shmem: 42304 kB
Slab: 24528 kB
SReclaimable: 12108 kB
SUnreclaim: 12420 kB
KernelStack: 2128 kB
PageTables: 5676 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 577120 kB
Committed_AS: 1675164 kB
VmallocTotal: 1114112 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
CmaTotal: 8192 kB
CmaFree: 6796 kB
If I do that :
pi@raspberrypi:/tmp $ ./a.out 750
ko
750 is to large, but
pi@raspberrypi:/tmp $ ./a.out 600 &
[1] 1525
pi@raspberrypi:/tmp $ ok
The used memory (top etc) doesn't reflect the 600Mo because I do not read/write in them
proc/meminfo
gives :
MemTotal: 949448 kB
MemFree: 282860 kB
MemAvailable: 626016 kB
Buffers: 39432 kB
Cached: 362860 kB
SwapCached: 0 kB
Active: 362696 kB
Inactive: 260580 kB
Active(anon): 199880 kB
Inactive(anon): 41392 kB
Active(file): 162816 kB
Inactive(file): 219188 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 102396 kB
SwapFree: 102396 kB
Dirty: 624 kB
Writeback: 0 kB
AnonPages: 220988 kB
Mapped: 215672 kB
Shmem: 41788 kB
Slab: 24788 kB
SReclaimable: 12296 kB
SUnreclaim: 12492 kB
KernelStack: 2136 kB
PageTables: 5692 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 577120 kB
Committed_AS: 2288564 kB
VmallocTotal: 1114112 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
CmaTotal: 8192 kB
CmaFree: 6796 kB
And I can again do
pi@raspberrypi:/tmp $ ./a.out 600 &
[2] 7088
pi@raspberrypi:/tmp $ ok
pi@raspberrypi:/tmp $ jobs
[1]- stopped ./a.out 600
[2]+ stopped ./a.out 600
pi@raspberrypi:/tmp $
Even the total is too large for the memory + swap, /proc/meminfo
gives :
MemTotal: 949448 kB
MemFree: 282532 kB
MemAvailable: 626112 kB
Buffers: 39432 kB
Cached: 359980 kB
SwapCached: 0 kB
Active: 365200 kB
Inactive: 257736 kB
Active(anon): 202280 kB
Inactive(anon): 38320 kB
Active(file): 162920 kB
Inactive(file): 219416 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 102396 kB
SwapFree: 102396 kB
Dirty: 52 kB
Writeback: 0 kB
AnonPages: 223520 kB
Mapped: 212600 kB
Shmem: 38716 kB
Slab: 24956 kB
SReclaimable: 12476 kB
SUnreclaim: 12480 kB
KernelStack: 2120 kB
PageTables: 5736 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 577120 kB
Committed_AS: 2876612 kB
VmallocTotal: 1114112 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
CmaTotal: 8192 kB
CmaFree: 6796 kB
If I write in the memory of %1 then stop it I have a lot of swap done on the flash
pi@raspberrypi:/tmp $ %1
./a.out 600
done
^Z
[1]+ stopped ./a.out 600
now there is almost no free swap and almost no free memory, /proc/meminfo
gives
MemTotal: 949448 kB
MemFree: 33884 kB
MemAvailable: 32544 kB
Buffers: 796 kB
Cached: 66032 kB
SwapCached: 66608 kB
Active: 483668 kB
Inactive: 390360 kB
Active(anon): 462456 kB
Inactive(anon): 374188 kB
Active(file): 21212 kB
Inactive(file): 16172 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 102396 kB
SwapFree: 3080 kB
Dirty: 96 kB
Writeback: 0 kB
AnonPages: 740984 kB
Mapped: 61176 kB
Shmem: 29288 kB
Slab: 21932 kB
SReclaimable: 9084 kB
SUnreclaim: 12848 kB
KernelStack: 2064 kB
PageTables: 7012 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 577120 kB
Committed_AS: 2873112 kB
VmallocTotal: 1114112 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
CmaTotal: 8192 kB
CmaFree: 6796 kB
%1 is still waiting on the getchar, if I do the same for %2 it works but in fact because the process %1 disappear (without message on the shell)
The behavior is the same if I malloc (giving a second argument to the program)
See also What is the purpose of MAP_ANONYMOUS flag in mmap system call?