Why I can't map memory with mmap
Kevin O'Gorman
kogorman at gmail.com
Mon Aug 18 14:30:28 EDT 2014
Now I'm befuddled. I modified the source so that it was easy to try
different combinations. If I sudo it, I can map a 1GiB (1<<30) private
anonymous region if I sudo the program. I cannot find any combination with
MAP_HUGETLB that works at all.
Here it is in working form, with an anonymous map and no backing file.
The mmap request is for a single byte, so it works for ordinary users Try
uncommenting the MAP_HUGETLB line, and I'd love to hear about a version
that works, even if it's only for root.
Since I'm aiming for a huge memory region, I figured HUGETLB would make
sense to limit the overhead.
============================ CUT HERE ================
/**
* @file
* <pre>"Find out the limits on locked memory"
* Last Modified: Mon Aug 18 11:21:23 PDT 2014
* @author Kevin O'Gorman
*/
#define _GNU_SOURCE /* enable some of the mmap flags */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
/* for getrlimit(2) */
#include <sys/time.h>
#include <sys/resource.h>
/* for open(2) */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
int
main(int argc, char *argv[])
{
void *where;
size_t length = 1;
struct rlimit rlim;
int flags = 0;
int fd = -1;
// fd = open("solvedtaq", O_RDWR); if (fd == -1) perror("open");
printf("fd is %d\n", fd);
// flags |= MAP_HUGETLB;
flags |= MAP_PRIVATE;
flags |= MAP_LOCKED;
flags |= MAP_ANONYMOUS;
if (getrlimit(RLIMIT_MEMLOCK, &rlim) == 0) {
printf("RLIMIT_MEMLOCK: hard: %lld, soft: %lld\n", (long
long)rlim.rlim_max, (long long)rlim.rlim_cur);
} else {
perror("getrlimit failed");
}
where = mmap(NULL, length, PROT_READ | PROT_WRITE, flags, fd, 0);
if (where != MAP_FAILED) {
printf("Mapped at %p\n", where);
} else {
perror("Mapping failed");
}
return EXIT_SUCCESS;
}
============================ CUT HERE ================
On Mon, Aug 18, 2014 at 10:24 AM, Kevin O'Gorman <kogorman at gmail.com> wrote:
>
> On Mon, Aug 18, 2014 at 9:46 AM, <Valdis.Kletnieks at vt.edu> wrote:
>
>> On Mon, 18 Aug 2014 08:15:12 -0700, "Kevin O'Gorman" said:
>>
>> > maybe someone here can help me figure out how to map a big (really big)
>> > work area and lock it in memory.
>>
>> What problem are you trying to solve by doing this? It usually doesn't
>> make
>> sense to lock more than a small chunk in memory - that's mostly for crypto
>> programs like PGP that are paranoid about keys being written to swap
>> spaces,
>> and a *very* few highly performance oriented programs. 99.8% of the time,
>> the kernel will do a reasonable job of making sure the right pages are in
>> memory.
>>
>> Plus, programmers almost always over-estimate what they *really* need to
>> lock
>> down. The end result is that performance ends up being *worse*, because
>> they
>> lock out more than needed, leaving all the rest of the processes on the
>> system
>> fighting over a too-small pool of pages. Really sucks when you actually
>> have
>> to read from disk every I/O because you no longer have an in-core file
>> cache :)
>>
>> I'm solving a huge alpha-beta search problem, and want a huge cache table
> tocheck permutations. That's why I increased RAM from 8 to 32 GB, and would
> be happy to use the extra 24GB all for the cache. (Cache table is like a
> hash table but with collisions causing replacement rather than chaining).
>
> Even in my small tests, the cache is giving me speedups in the
> neighborhood of
> a million, so I'm going big. Because this is about speed, I do not *ever*
> want it to
> swap.
>
>
>> > I wrote a little test program to try this out, and it fails. As a
>> regular
>> > user, perror() tells me some "resource is temporarily unavailable". As
>> > root, it says it "cannot allocate memory". I'm only asking for 1 byte.
>>
>> > where = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE |
>> > MAP_ANONYMOUS | MAP_HUGETLB | MAP_LOCKED | MAP_POPULATE, -1, 0);
>>
>> Remember that no matter what "length" you pass, even if it's 1 byte, the
>> kernel has to allocate at least enough integer pages to cover the request.
>> You ask for 4100 bytes, it has to allocate 2 pages because 4096 isn't
>> quite big enough.
>>
>> And if you ask for MAP_HUGETLB, you're going to get at least 1 page.
>> Which
>> is probably 2M in size. And that can be painful if the default max
>> lockable
>> memory is less than 2M (at least on my Fedora Rawhide box, it's all of
>> 64K). There's also some interaction danger with MAP_POPULATE and memory
>> fragmentation. But both POPULATE and HUGETLB have a high chance of
>> not playing well with LOCKED.
>>
>
> Good catch. Indeed, removing MAP_HUGETLB allows the program to succeed.
> I'll try increasing the resource limit, but may have to have to sudo it, do
> the mmap() and then chusr to my real ID.
>
> The fd of -1 that some folks thought might be a problem is suggested in
> the man page for use with MAP_ANONYMOUS. That flag means I'm not using a
> backing file, after all.
>
> --
> Kevin O'Gorman
>
> programmer, n. an organism that transmutes caffeine into software.
> Please consider the environment before printing this email.
>
--
Kevin O'Gorman
programmer, n. an organism that transmutes caffeine into software.
Please consider the environment before printing this email.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20140818/5f6fa068/attachment.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/gif
Size: 441 bytes
Desc: not available
Url : http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20140818/5f6fa068/attachment.gif
More information about the Kernelnewbies
mailing list