Имейте в виду, что размер адресного пространства для «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).