Why doesn't the large mmap () call work?

I am trying to use mmap() to manage virtual memory. I want to reserve and lock a memory area. I checked 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 launched several copies of my program (say 6) from the terminal. I have never seen a “memory allocation failed” in any. I work on 64-bit Ubuntu with 4 GB of RAM. Can someone tell me something about this?

+6
source share
4 answers

mmap reserves the virtual address space of the process, but does not immediately allocate physical memory for it. Therefore, on a 64-bit platform, you can reserve a huge amount without failures (although you still need to check for a failure, there is no code in your example). Physical pages of RAM are allocated later when accessing memory.

mprotect simply changes the read / write access of the reserved memory; he will not force him to remain in RAM either. You will get the same effect by passing PROT_READ | PROT_WRITE PROT_READ | PROT_WRITE instead of PROT_NONE in mmap and deleting the mprotect call.

If you need RAM located in RAM immediately, use mlock for this. It will not work if access to RAM is insufficient. On many Linux platforms (including Ubuntu) there is a resource limit ( RLIMIT_MEMLOCK ) that limits the amount of memory that any process can block; you can configure it with ulimit -l .

+11
source

mmap is useful for preparing the mapping of the memory you are requesting, but it does not allocate it to your program. The kernel will take care to allocate memory when you access it, so mmap -ing 8 GB is possible in 4 GB memory if you do not access these 8GB at the same time.

+1
source

You must first check the result of mmap . If it returns MAP_FAILED , it means that the allocation failed. The kernel would not actually allocate as much memory at once, but rather would plan physical or replaced space on demand when accessing the corresponding areas of this block.

In your specific case, you do not need a separate call to mprotect , since the transfer of these flags for the entire area can be done during the mmap call:

 pMemory = mmap(NULL, maxCapacity, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (pMemory == MAP_FAILED) { /* allocation failed */ } 
0
source

First, you must tell Linux that you want it to commit:

 echo "2" > /proc/sys/vm/overcommit_memory 

Otherwise, it preserves the obsolete default value (starting from the moment when Linux was an OS toy), allowing you to unlimitedly overload and making your applications crash crash when they run out of physical memory.

Also, as others have said, you need to check the return value of mmap for MAP_FAILED , and there is no need to use mprotect . Just pass the correct PROT_* values ​​to mmap to get started.

0
source

Source: https://habr.com/ru/post/907567/


All Articles