В 64-битном процессе мой запрос mmap / malloc будет отклонен? - PullRequest
13 голосов
/ 07 февраля 2011

Адресное пространство для 64-битной адресации абсолютно огромно.У меня есть программа, которая будет mmap несколько кусков памяти, каждый порядка 100 - 500 МБ.Я неизбежно буду перераспределять несколько раз, что может привести к некоторой фрагментации доступного смежного пространства.

Какая бы ни была фрагментация пространства, она наверняка будет незначительной в отношении доступного адресного пространства.* Мой вопрос таков: учитывая эти ограничения, при нормальных обстоятельствах могу ли я ожидать, что все mmap запросы будут выполнены успешно (т.е. не сбои из-за фрагментации)?Какие причины могут быть для них неудачными?

Я знаю, что куча не имеет всего пространства для себя, но я думаю, что она имеет подавляющее большинство.

Mac OS / Linux.

Ответы [ 4 ]

27 голосов
/ 07 февраля 2011

Имейте в виду, что размер адресного пространства для «64-битных операционных систем» не обязательно покрывает весь 64-битный диапазон.

На x64 (64-битной x86, также называемой AMD64), например, фактически доступный виртуальныйдиапазон адресов «всего» 2x128TB, т.е. 48 бит в двух непересекающихся блоках по 47 бит.В некоторых системах SPARC это 2x2 ТБ или 2x8 ТБ (41/44 бит).Это связано с тем, как MMU работает на этих платформах.

В дополнение к этим архитектурным ограничениям здесь также играет роль способ, которым операционная система размещает ваши адресные пространства.
64-битная Windows на x64,например, ограничивает размер виртуального адреса (даже 64-битного) приложения до 8 ТБ (каждое ядро ​​и пользовательская сторона 1 ).

В системах UN * X (включая Linux, MacOSX и * BSD), существует RLIMIT_AS, к которому можно обратиться с помощью getrlimit(), и - в пределах системных ограничений - настроить с помощью setrlimit.Команда ulimit использует их.Однако они возвращают / устанавливают верхнюю границу, то есть разрешенное общее виртуальное адресное пространство, включая все сопоставления, которые может создать процесс (через mmap() или malloc backend, sbrk()).Но общий размер адресного пространства отличается от максимального размера одного сопоставления ...

Учитывая это, не так сложно исчерпать виртуальное адресное пространство даже в 64-битной Linux;просто попробуйте для теста mmap() тот же файл 500 ГБ, скажем, двести раз.В конечном итоге mmap завершится с ошибкой.

Вкратце:

  • mmap() определенно завершится с ошибкой, как только вы выйдете из виртуального адресного пространства.Что, на удивление, достижимо на многих «64-битных» архитектурах просто потому, что виртуальные адреса могут иметь меньше 64 значащих битов.Точное ограничение зависит от вашего процессора и операционной системы, а верхняя граница может быть запрошена через getrlimit(RLIMIT_AS) или установлена ​​через setrlimit(RLIMIT_AS).
  • Фрагментация адресного пространства может происходить на 64-битной основе, часто используя mmap() / munmap() в разных порядках и с блоками разного размера.Это в конечном итоге ограничит максимальный размер, который вы сможете отобразить как один чанк.Предсказать, когда именно это произойдет, сложно, так как это зависит от вашей «истории отображения» и алгоритма выделения виртуального адресного пространства операционной системы.Если ASLR (рандомизация размещения адресного пространства) выполняется ОС, это может быть непредсказуемым в деталях и не совсем воспроизводимым.
  • malloc() также завершится с ошибкой не позднее достижения общего предела VA для систем (как в Linux), где overcommit позволяет вам «запросить» больше памяти, чем есть в системе (физический + swap).
  • На машинах / операционных системах, где не включена overcommit, malloc() и mmap() с MAP_ANON и / или MAP_PRIVATE произойдет сбой, когда физический + подкачка исчерпан, потому что для этих типов сопоставлений требуется резервное копирование по фактической памяти или подкачке.

Небольшое техническое обновление: как x86 иSparc, упомянутый выше, новый ARMv8 (64-битный ARM, в Linux называемый «AArch64»), также имеет «разделенное» адресное пространство / дыру в адресном пространстве - из 64 битов в адресе только 40 имеют отношение.Linux предоставляет 39 бит для пользователя, виртуальные адреса 0 ... и выше, 39 бит для ядра, виртуальные адреса ... 0xFFFFFFFF.FFFFFFFF, поэтому ограничение составляет 512 ГБ (минус то, что используется уже во время попытки приложения mmap).
См. комментарии здесь (из серии исправлений ядра для архитектуры AArch64).

8 голосов
/ 07 февраля 2011

mmap и malloc могут завершиться ошибкой из-за недостатка физической памяти (ОЗУ + обмен).В общем, стандарт Unix говорит о диапазонах адресов, которые «разрешены для адресного пространства процесса».Кроме того,

Если будет объявлена ​​функция для возврата кода ошибки в случае затруднений, вы должны проверить этот код, да, даже если проверки утроят размер вашего кода и произведутболит в твоих печатающих пальцах, потому что если ты думаешь, что «со мной этого не случится», боги обязательно накажут тебя за твое высокомерие.*

0 голосов
/ 07 февраля 2011

Что ж, библиотека OS / C может свободно решать, достаточно ли памяти или нет.На самом деле у вас нет возможности узнать, как он решает это (это, очевидно, зависит от ОС, возможно, даже настраивается), но возможно, что в какой-то момент ОС скажет «больше нет».

Возможные причины сбоявыделить память:

  • Linux будет перегружать память, но это настраивается.В зависимости от того, как он настроен, вы можете получить ENOMEM, как только превысите RAM + Swap.
  • Если ограничения памяти были установлены с помощью ulimit, вы можете получить ENOMEM даже раньше
0 голосов
/ 07 февраля 2011

Просто проверьте список ошибок в man mmap.

...