Search code examples
cposixmemory-locking

Lock the memory to physical RAM in C for the dynamically allocate pointer


I want to lock the memory to physical RAM in C with mlock and munlock, but I'm unsure about the correct usage.

Allow me to explain in a step by step scenario:

Let's assume that I dynamically allocate a pointer using calloc:

char * data = (char *)calloc(12, sizeof(char*));

Should I do mlock right after that?

Let's also assume that I later attempt to resize the memory block with realloc:

(char *)realloc(data, 100 * sizeof(char*));

Note the above increase amount ( 100 ) is random and sometimes i will decrease the memory block.

Should I first do munlock and then mlock again to address the changes made?

Also when I want to free the pointer data later, should I munlock first?

I hope someone can please explain the correct steps to me so I can understand better.


Solution

  • From the POSIX specification of mlock() and munlock():

    The mlock() function shall cause those whole pages containing any part of the address space of the process starting at address addr and continuing for len bytes to be memory-resident until unlocked or until the process exits or execs another process image. The implementation may require that addr be a multiple of {PAGESIZE}.

    The munlock() function shall unlock those whole pages containing any part of the address space of the process starting at address addr and continuing for len bytes, regardless of how many times mlock() has been called by the process for any of the pages in the specified range. The implementation may require that addr be a multiple of {PAGESIZE}.

    Note that:

    • Both functions work on whole pages
    • Both functions might require addr to be a multiple of page size
    • munlock doesn't use any reference counting to track lock lifetime

    This make it almost impossible to use them with pointers returned by malloc/calloc/realloc as they can:

    • Accidently lock/unlock nearby pages (you might unlock pages that must be memory-resident by accident)
    • Might return pointers that are not suitable for those functions

    You should use mmap instead or any other OS-specific mechanism. For example Linux has mremap which allows you to "reallocate" memory. Whatever you use, make sure mlock behavior is well-defined for it. From Linux man pages:

    If the memory segment specified by old_address and old_size is locked (using mlock(2) or similar), then this lock is maintained when the segment is resized and/or relocated. As a consequence, the amount of memory locked by the process may change.


    Note Nate Eldredge's comment below:

    Another problem with using realloc with locked memory is that the data will be copied to the new location before you have a chance to find out where it is and lock it. If your purpose in using mlock is to ensure that sensitive data never gets written out to swap, this creates a window of time where that might happen.