I'm experimenting with shm_open
in Linux and I'm running into problems. I'm frequently resizing a shared memory segment with ftrunc
and using mmap
to remap the resized segment. However, right around the 20 megabyte mark I get ENOMEM
from mmap
.
I have attempted the following to do to resolve the issue:
First, I found out about these sysctl
parameters. I reconfigured them:
kernel.shmmax = 268435456
kernel.shmall = 2097152
(shmall
is specified in pages)
The issue still occurred after this. Investigating the details of the resize that causes the issue revealed that the call made to ftrunc
to resize the shared memory object succeeded (the corresponding file in /dev/shm
had the requested new size).
Documentation from here suggests three possible causes for an ENOMEM
errno
:
[ENOMEM]
MAP_FIXED was specified, and the range [addr,addr+len) exceeds that allowed for the address space of a process; or, if MAP_FIXED was not specified and there is insufficient room in the address space to effect the mapping.
[ENOMEM]
[ML] The mapping could not be locked in memory, if required by mlockall(), because it would require more space than the system is able to supply.
[ENOMEM]
[TYM] Not enough unallocated memory resources remain in the typed memory object designated by fildes to allocate len bytes.
I am not using MAP_FIXED
or locking, and the size of the image in /dev/shm
suggests that the third reason is not the problem. My mmap
call looks like this:
mmap(mem, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
where mem
initially is 0 and thereafter refers to the last address mmap
successfully mapped.
I found information suggesting that ulimit
settings could be limiting the memory mappable into a single process, but I don't think the problem was here. Just in case, ulimit -a
looks like this on my machine:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65536
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
I misread the documentation for mmap
, which says that mmap
returns a mapping based on the first parameter (the previously mapped address in my case), and the result is defined by implementation. I took this as a suggestion that mmap
might remap my previous mapping for me, but this was certainly not the case. this might only have been the case if I had used the MAP_FIXED
flag, but I avoided this because the documentation recommended against it.
In any case, it was necessary to use munmap
to remove the previous mapping before creating a new one.