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.
For example:
1
mmap(..., PROT_NONE, ...);
This makes the region inaccessible and non-resident — a virtual reservation without committing physical resources.
This is a transient state. The memory is accessible but not yet backed by physical memory. It will be lazily paged
in on first access. This lazy allocation lets Linux economize on physical memory. Many programs request large amounts
of memory, but never use most of it — like travel insurance that often goes unused.
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’s no point in keeping it resident. So this state is almost always
transient, where the memory is expected to become accessible soon.
You can create this state by first forcing population, then removing access:
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.
if (addr == MAP_FAILED) { perror("mmap"); exit(1); }
printf("Reserved some 4K-pages at: %p\n\n", addr);
res = mincore(addr, num_pages * PS, vec); assert(res == 0);
puts("Reserved but no physical mem is used"); for (int i = 0; i < num_pages; ++i) { assert((vec[i] & 1) == 0); printf("%d", (vec[i] & 1)); } puts("\n");
puts("Write to the the first 5 pages"); for (int i = 0; i < 5; ++i) ((char *)addr)[i * PS] = 1;
res = mincore(addr, num_pages * PS, vec); assert(res == 0);
for (int i = 0; i < num_pages; ++i) { assert((vec[i] & 1) == (i < 5)); printf("%d", (vec[i] & 1)); } puts("\n");
puts("Write to the rest of pages"); for (int i = 5; i < num_pages; ++i) ((char *)addr)[i * PS] = 1;
res = mincore(addr, num_pages * PS, vec); assert(res == 0); for (int i = 0; i < num_pages; ++i) assert((vec[i] & 1) == 1); for (int i = 0; i < num_pages; ++i) printf("%d", (vec[i] & 1)); puts("\n");
// 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;