I try to use mmap()
to manipulate virtual memory. I want to reserve and commit a region of memory. I tested this code:
const unsigned long gygabyte = 1024 * 1024 * 1024;
const unsigned long gygabyteCount = 2;
const unsigned long maxCapacity = gygabyteCount * gygabyte;
int main()
{
char* pMemory;
pMemory = (char*)mmap(NULL, maxCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if ( mprotect(pMemory, maxCapacity, PROT_READ | PROT_WRITE) != 0 )
{
cout << "Memory Allocation has failed" << endl;
}
usleep(-1);
return 0;
}
I ran several copies of my program (say 6) from a terminal. I didn't ever see "Memory Allocation has failed" in any one. I'm running on 64-bit Ubuntu with 4GB RAM. Can anyone tell me something about this?
Almost always, memory is much faster than disk, and malloc is not what's costing time. The mmap code is faster because for your program, mmap has resulted in either less disk access, or more efficient disk access, than whatever reads and writes you compared against.
Upon successful completion, the mmap() function returns the address at which the mapping was placed; otherwise, it returns a value of MAP_FAILED, which has a value of 0, and sets errno to indicate the error.
It doesn't actually put anything into physical memory at all. After you call mmap , the allocated region probably doesn't even point to physical memory: accessing it will cause a page fault. This kind of page fault is transparently handled by the kernel, in fact, this is one of the kernel's primary duties.
Even though it is important and often used, mmap can be slow and inconsistent in its timing. Mmap maps memory pages directly to bytes on disk. With mmap, whenever there is a pagefault, the kernel pulls the page directly from disk into the program's memory space.
mmap
reserves a region of the process's virtual address space, but does not immediately allocate physical RAM for it. Therefore, on a 64-bit platform, you can reserve a vast amount without failure (although you still need to check for failure; your example code doesn't). Physical pages of RAM are allocated later when the memory is accessed.
mprotect
just changes the read/write access of the reserved memory; it won't make it resident in RAM either. You would get the same effect by passing PROT_READ | PROT_WRITE
instead of PROT_NONE
to mmap
, and removing the call to mprotect
.
If you need the memory to be resident in RAM straight away, then use mlock
for that. It will fail if there isn't enough RAM available. On many linux platforms (including Ubuntu), there is a resource limit (RLIMIT_MEMLOCK
) which restricts how much memory any process can lock; you can adjust this with ulimit -l
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With