Ответ 1
Помните, что размер адресного пространства для "64-битных операционных систем" не обязательно покрывает полный 64-битный диапазон.
В x64 (64 бит x86, ака 'AMD64'), например, фактический диапазон доступных виртуальных адресов "только" 2x128TB, т.е. 48 бит в двух непересекающихся 47-битных фрагментах. В некоторых системах SPARC это 2x2TB или 2x8TB (41/44 бит). Это связано с тем, как MMU работает на этих платформах.
В дополнение к этим архитектурным ограничениям, то, как операционная система определяет ваши адресные пространства, также играет здесь роль. Например, 64-битная Windows на x64 ограничивает размер виртуального адреса (даже 64-битного) приложения до 8 ТБ (каждое ядро и пользовательская сторона 1).
В системах UN * X (включая Linux, MacOSX и * BSD) существует RLIMIT_AS
, который можно запросить через getrlimit()
, и - в пределах системных ограничений - отрегулируйте через setrlimit
. Для этого используется команда ulimit
. Они возвращают/устанавливают верхнюю границу, т.е. Допустимое общее виртуальное адресное пространство, включая все сопоставления, которые может создать процесс (через mmap()
или бэкенд malloc
, sbrk()
).
Но общий размер адресного пространства отличается от максимального размера одного отображения...
Учитывая это, не так сложно исчерпать виртуальное адресное пространство даже на 64-битной Linux; просто попробуйте, для теста, mmap()
тот же 500GB файл, скажем, в двести раз. В конце концов mmap не удастся.
Короче:
-
mmap()
, безусловно, будет терпеть неудачу, если вы вышли из виртуального адресного пространства. Что, как ни удивительно, достижимо на многих "64-битных" архитектурах, просто потому, что виртуальные адреса могут иметь менее 64 значащих бит. Точная отсечка зависит от вашего процессора и вашей операционной системы, а верхняя граница может быть запрошена черезgetrlimit(RLIMIT_AS)
или установлена черезsetrlimit(RLIMIT_AS)
. - Фрагментация адресного пространства может происходить на 64-битной часто при использовании
mmap()
/munmap()
в разных порядках и блоках разного размера. Это в конечном итоге ограничит максимальный размер, который вы сможете отобразить в виде одного фрагмента. Предсказание того, когда это произойдет, сложно, так как оно зависит от вашей истории сопоставления и алгоритма распределения виртуального адресного пространства операционных систем. Если ASLR (рандомизация размещения адресного пространства) выполняется ОС, это может быть непредсказуемо подробно, а не точно воспроизводимым. -
malloc()
также завершится не позднее достижения полного предела VA в системах (например, Linux), где overcommit позволяет "запрашивать" больше памяти, чем в системе (физическая + своп). - В машинах/операционных системах, где не включен overcommit, обе версии
malloc()
иmmap()
сMAP_ANON
и/илиMAP_PRIVATE
будут терпеть неудачу, если физический + swap будет исчерпан, потому что для этих типов сопоставлений требуется резервное хранилище на фактическая память или своп.
Небольшое техническое обновление: Как и x86 и sparc, упомянутые выше, новый ARMv8 (64-битный ARM, называемый "AArch64" в Linux) MMU также имеет "разделенное" адресное пространство/адресное пространство - из 64 бит в адрес, всего 40. Linux дает 39 бит для пользователя, виртуальные адреса 0 ...
и далее, 39 бит для ядра, виртуальные адреса ... 0xFFFFFFFF.FFFFFFFF
, поэтому предел составляет 512 ГБ (минус то, что используется в то время, когда приложение пытается использовать mmap
).
См. комментарии здесь (из серии исправлений ядра ядра AArch64).