Как получить объем виртуальной памяти, доступной в C ++? - PullRequest
3 голосов
/ 18 ноября 2010

Я хотел бы отобразить файл в память, используя функцию mmap, и хотел бы знать, достаточен ли объем виртуальной памяти на текущей платформе для сопоставления огромного файла. Для системы 32 я не могу отобразить файл размером более 4 ГБ.
std::numeric_limits<size_t>::max() даст мне объем адресуемой памяти или есть какой-то другой тип, который я должен проверить (off_t или что-то еще)?

Как указал Ли Райан в своем комментарии, «виртуальная память» здесь используется не по назначению. Однако возникает вопрос: есть тип, связанный с указателем, и он имеет максимальное значение, которое определяет верхний предел того, что вы можете адресовать в вашей системе. Что это за тип? Это size_t или, возможно, ptrdiff_t?

Ответы [ 5 ]

1 голос
/ 18 ноября 2010

Ваш перефразированный вопрос «верхний предел того, что вы можете адресовать в своей системе», несколько вводит в заблуждение;это специфическая аппаратная архитектура.Существуют 64-битные архитектуры (x64, sparc), в которых MMU успешно разрешает (uintptr_t) (- 1) в качестве допустимого адреса, то есть вы можете сопоставить что-то с последней страницей 64-битного адресного пространства.Позволяет ли операционная система приложению делать это или нет - это опять совершенно другой вопрос ...

Для пользовательских приложений "высокая оценка" не всегда (а) фиксирована априори.Он настраивается, например, на Solaris или Linux.Вот тут-то и приходит getrlimit (RLIMIT_AS).

Обратите внимание, что опять-таки, по спецификации, ничто не помешает (странному) дизайну операционной системы выбирать, например, помещать стеки и кучи приложений на «низкие» адреса, покаразмещение кода по «старшим» адресам на платформе с дырами в адресном пространстве.Там вам понадобятся полные 64-битные указатели, вы не можете их уменьшить, но может быть произвольное количество «недоступных / недействительных» диапазонов, которые никогда не будут доступны вашему приложению.

1 голос
/ 18 ноября 2010

Дело в том, что размер указателя ничего не говорит вам о том, какая часть этого «адресного пространства» фактически доступна для вас, то есть может отображаться как один непрерывный фрагмент.

Ограничено:

  • операционная система. Он может выбрать только подмножество теоретически возможного диапазона адресов, доступного для вас, потому что сопоставимая память необходима для собственных целей ОС (например, для отображения кадрового буфера видеокарты и, конечно, для использования самой ОС). ).
  • настраиваемые пределы. В Linux / UNIX команда "ulimit" соотв. Системный вызов setrlimit () позволяет по-разному ограничивать максимальный размер адресного пространства приложения, и Windows имеет аналогичные параметры через параметры реестра.
  • история применения. Если приложение широко использует отображение памяти, адресное пространство может фрагментироваться, ограничивая максимальный размер «доступных» смежных виртуальных адресов.
  • аппаратная платформа. Некоторые процессоры имеют адресные пространства с «дырами»; Примером этого является 64-битный x86, где указатели действительны, только если они находятся между 0x0..0x7fffffffffff или 0xffff000000000000 и 0xffffffffffffffff. То есть у вас есть 2x128TB вместо полных 16EB. Думайте об этом как о 48-битных "подписанных" указателях ...

Наконец, не путайте «доступную память» и «доступное адресное пространство». Существует различие между выполнением malloc (someBigSize) и mmap (..., someBigSize, ...), потому что первое может потребовать наличия физической памяти для удовлетворения запроса, в то время как второе обычно требует только наличия достаточно большого свободного диапазон адресов.

Для платформ UNIX часть ответа заключается в использовании getrlimit (RLIMIT_AS), поскольку это дает верхнюю границу для текущего вызова вашего приложения - как уже было сказано, пользователь и / или администратор могут это настроить. Вы гарантированы, что любая попытка отобразить области, большие чем это, потерпит неудачу.

1 голос
/ 18 ноября 2010

Привет, вы можете использовать GlobalMemoryStatusEx и VirtualQueryEx, если вы пишете в win32

1 голос
/ 18 ноября 2010

size_t должен быть достаточно большим, чтобы хранить как можно больший единственный смежный объект.То, что может не совпадать с размером адресного пространства (например, в системах с моделью сегментированной памяти)

Однако на общих платформах с плоским пространством памяти дваравны, и поэтому вы можете с легкостью использовать size_t на практике, если знаете целевой процессор.

В любом случае, это действительно не говорит вам ничего полезного.Конечно, 32-разрядный процессор имеет 4 ГБ памяти, поэтому size_t - это 32-разрядное целое число без знака.Но это ничего не говорит о том, сколько вы можете выделить.Некоторая часть пространства памяти используется ОС.А некоторые части уже используются вашим собственным приложением: для отображения исполняемого файла в память (а также любые динамические библиотеки, которые он может использовать), для стека каждого потока, выделенной памяти в куче и т. Д.

Итакнет, такие уловки, как взятие размера size_t, немного расскажут вам об адресном пространстве, в котором вы работаете, но ничего очень полезного.Вы можете спросить у ОС, сколько памяти используется вашим процессом и другими показателями, но опять же, это не очень вам помогает.Процесс может использовать всего пару мегабайт, но он распределен по стольким небольшим выделениям, что невозможно найти непрерывный блок памяти размером более 100 МБ, скажем.Итак, на 32-разрядной машине с процессом, который почти не использует память, вы вряд ли будете делать такое распределение.(И даже если бы у ОС был волшебный WhatIsTheLargestPossibleMemoryAllocationICanMake() API, этот все же не помог бы вам. Он бы сказал вам, что вам нужно с момента назад . У вас нет гарантиичто ответ все равно будет действительным к тому времени, когда вы попытаетесь сопоставить файл.

На самом деле лучшее, что вы можете сделать, это попытаться сопоставить файл и посмотреть, не получится ли это.

0 голосов
/ 18 ноября 2010

Вы можете попробовать sizeof(int*).Это даст вам длину (в байтах) указателя на целевой платформе.Таким образом, вы можете узнать, насколько велика адресуемая область.

...