Why I can't map memory with mmap
Mandeep Sandhu
mandeepsandhu.chd at gmail.com
Mon Aug 18 16:25:45 EDT 2014
I sent the previous mail too early!
I got it to work for root user by setting "/proc/sys/vm/nr_hugepages" to 20
as suggested in Documentation/vm/hugetlbpage.txt. Now I'm able to mmap it
and it reflects the same in /proc/meminfo as well! :)
HTH,
-mandeep
On Mon, Aug 18, 2014 at 1:23 PM, Mandeep Sandhu <mandeepsandhu.chd at gmail.com
> wrote:
> I tried your program and got the same result, i.e "Resource temporarily
> unavailable" for an ordinary user and "Cannot allocate memory" if run as
> root.
>
> However, reading the Huge TLB pages doc
> (Documentation/vm/hugetlbpage.txt), I saw the following para which might
> explain the error:
> ...
> Once a number of huge pages have been pre-allocated to the kernel huge page
> pool, a user with appropriate privilege can use either the mmap system call
> or shared memory system calls to use the huge pages. See the discussion of
> Using Huge Pages, below.
>
> The administrator can allocate persistent huge pages on the kernel boot
> command line by specifying the "hugepages=N" parameter, where 'N' = the
> number of huge pages requested. This is the most reliable method of
> allocating huge pages as memory has not yet become fragmented.
> ...
> ...
>
> I don't have my kernel booted with it, so that might explain why mmap fails for MAP_HUGETLB.
>
> I can't restart my machine with the new flag right now, but maybe you can try.
>
> HTH,
>
> -mandeep
>
>
>
>
> On Mon, Aug 18, 2014 at 11:30 AM, Kevin O'Gorman <kogorman at gmail.com>
> wrote:
>
>> 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.
>>
>> _______________________________________________
>> Kernelnewbies mailing list
>> Kernelnewbies at kernelnewbies.org
>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20140818/731e05cf/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/731e05cf/attachment.gif
More information about the Kernelnewbies
mailing list