mmap возвращает ENOMEM с файловым объектом shm_open

Экспериментировал с shm_open в linux и столкнулся с проблемами. Я часто изменяю размер сегмента совместно используемой памяти с помощью ftrunc и использую mmap для переназначения сегмента с измененным размером. Тем не менее, около отметки в 20 мегабайт я получаю ENOMEM от mmap.

Что я пытался сделать, чтобы решить эту проблему:

во-первых, я узнал об этих параметрах sysctl. я перенастроил их:

kernel.shmmax = 268435456
kernel.shmall = 2097152

(shmall указан на страницах)

проблема все еще возникла после этого. изучение деталей изменения размера, вызывающих проблему, выявило, что вызов, выполненный для ftrunc для изменения размера объекта общей памяти, завершился успешно (соответствующий файл в /dev/shm имел запрошенный новый размер).

Документация отсюда http://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html предлагает три возможных причины ошибки ENOMEM:


[ENOMEM] MAP_FIXED был указан, и диапазон [addr,addr+len) превышает допустимый для адресного пространства процесса; или, если MAP_FIXED не был указан, и в адресном пространстве недостаточно места для сопоставления.

[ENOMEM] [ML] [Option Start] Невозможно заблокировать отображение в памяти, если этого требует mlockall(), поскольку для этого потребуется больше места, чем может предоставить система. [Вариант Конец]

[ENOMEM] [TYM] [Option Start] Недостаточно нераспределенных ресурсов памяти в типизированном объекте памяти, обозначенном fildes, для выделения длинных байтов. [Вариант Конец]


я не использую MAP_FIXED или блокировку, а размер изображения в /dev/shm говорит о том, что третья причина - не проблема. мой вызов mmap выглядит так:

mmap (mem, длина, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)

где mem изначально равно 0 и после этого ссылается на последний успешно сопоставленный адрес mmap.

я нашел информацию о том, что настройки ulimit могут ограничивать отображаемую память в одном процессе, но я не думаю, что проблема была здесь. на всякий случай, ulimit -a выглядит так на моей машине:

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

я надеюсь, что это легко:)

1 ответ

Решение

Ну, я узнал, что моя проблема была на днях. я неправильно прочитал документацию для mmap, в которой говорится, что mmap возвращает отображение на основе первого параметра (ранее отображенный адрес в моем случае), а результат определяется реализацией. Я воспринял это как предположение, что mmap может переназначить мне мое предыдущее отображение, но это, конечно, не так. это могло быть только в том случае, если бы я использовал флаг MAP_FIXED, но я избежал этого, потому что документация рекомендована против него. в любом случае необходимо было использовать munmap, чтобы удалить предыдущее отображение перед созданием нового. я надеюсь, что этот пост поможет любому, кто совершит ту же глупую ошибку, что и я

Другие вопросы по тегам