This is the initial state — memory is reserved so that the address range cannot be used by other components of the
current process. There is no physical memory backing it yet.
This lazy allocation allows Linux to economize on physical memory. Many programs request large amounts of memory but
never use most of it — like travel insurance that often goes unused.
Of course, for this lazy scheme to work, the OS must be able to provide the physical memory when the region is accessed.
In other words, the OS has promised to supply this memory on demand, which is why this state is often referred to as
committed. The Committed_AS entry in /proc/meminfo reflects this commitment.
This is an unusual state. Memory is backed by physical pages but cannot be accessed due to its protection settings.
Normally, if memory is inaccessible, there is no reason for it to remain resident. So this state is almost always
transient, where the memory is expected to become accessible soon.
One can create this state by first writing to the memory (to make it resident and dirty), then removing access
permissions.
1 2 3
mmap(..., PROT_READ | PROT_WRITE, ...); memset(..., 0, ...); // to make mem dirty so that they must be preserved mprotect(..., PROT_NONE);
First, we allocate a few pages; since, by default, lazy mapping is used, none of them are resident in physical memory. A
page will be backed by physical memory on the first write into that page.
// Reserve one huge-page -- HugePages_Rsvd in /proc/meminfo is incremented. // By omitting MAP_NORESERVE, we get the guarantee that a successful mmap entails successful writes to the memory. // Otherwise, even though the mmap call succeeds, we may get a crash on writing the memory because no huge-page is // available. addr = mmap(nullptr, ps_2m * 1, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0); // MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0);
if (addr == MAP_FAILED) { perror("mmap"); exit(1); }
// huge-page mem has been pre allocated but not tied to our reserved mem yet res = mincore(addr, 10 * PS, vec); assert(res == 0);
puts("Reserved but no physical mem is used"); for (int i = 0; i < 10; ++i) { printf("%d", (vec[i] & 1)); }
puts("\n");
// write to the first byte puts("Write to the first 1 byte"); ((char *)addr)[0] = 1;