void *mremap(void *
int
Возвращает начальный адрес измененного отображения при успешном завершении или MAP_FAILED, если произошла ошибка
Изменяя отображение, ядро может переместить его в рамках виртуального адресного пространства процесса. Возможность такого перемещения определяется аргументом flags; это битовая маска, которая может быть равна либо нулю, либо следующим значениям.
• MREMAP_MAYMOVE — если указать данный флаг, ядро, исходя из требований к свободной памяти, может переместить отображение внутри виртуального адресного пространства процесса. В противном случае, если на текущем участке не хватает свободного места для расширения отображения, генерируется ошибка ENOMEM.
• MREMAP_FIXED (начиная с Linux 2.4) — этот флаг можно использовать только в сочетании с MREMAP_MAYMOVE. Его действие аналогично применению флага MAP_FIXED в вызове mmap() (см. раздел 45.10). Если его указать, то вызов mremap() сможет принять дополнительный аргумент void *new_address — адрес, выровненный по странице, куда следует переместить отображение. Любые другие отображения, находящиеся в диапазоне, заданном с помощью new_address и new_size, уничтожаются.
В случае успеха mremap() возвращает начальный адрес отображения. Поскольку данное значение может отличаться от предыдущего начального адреса (если был указан флаг MREMAP_MAYMOVE), указатели, ссылающиеся на этот участок, могут утратить свою актуальность. Следовательно, приложения, выполняющие вызов mremap(), должны ссылаться на адреса в отображенном участке с помощью отступов, избегая абсолютных значений.
В Linux существует функция realloc(), которая использует вызов mremap() для эффективного перемещения больших блоков памяти, выделенных ранее путем операции mmap() MAP_ANONYMOUS (я уже упоминал о данной возможности вызова malloc() из библиотеки glibc в разделе 45.7). Применение для этих целей вызова mremap() позволяет избежать копирования данных во время перемещения.
Некоторые приложения создают большие (обычно приватные и анонимные) отображения, но используют только небольшую часть выделенной памяти. Например, ряд научных программ выделяют огромные массивы, но помещают в разные его участки всего несколько элементов (такие массивы называют
Если бы ядро всегда выделяло (или резервировало) для таких отображений достаточно места в файле подкачки, то большая его часть тратилась бы впустую. Вместо этого оно способно резервировать страницы отображения по мере необходимости (то есть когда приложение пытается получить к ним доступ). Такой подход называется
Иными словами, отложенное резервирование позволяет перерасходовать пространство подкачки. Это работает до тех пор, пока все процессы не попытаются получить доступ ко всему диапазону адресов своих отображений. В таком случае физическая память и пространство подкачки будут исчерпаны и ядро будет вынуждено снизить давление на память, принудительно завершив один или несколько процессов. В идеале оно попытается выбрать процесс, вызывающий проблемы с памятью (см. описание
Способ резервирования пространства подкачки ядром зависит от использования флага MAP_NORESERVE при вызове mmap(), а также от интерфейсов /proc, которые влияют на перерасход пространства подкачки на уровне системы. Эти факторы сгруппированы в табл. 45.4.
Таблица 45.4. Управление резервированием пространства подкачки при вызове mmap()
Значение overcommit_memory
Указан ли флаг MAP_NORESERVE при вызове mmap()?
Нет
Да
0
Очевидный перерасход запрещается
Перерасход разрешен
1
Перерасход разрешен
Перерасход разрешен
2 (начиная с Linux 2.6)
Разрешается фиксированный перерасход
Файл /proc/sys/vm/overcommit_memory (доступный только в Linux) содержит целое число, определяющее поведение ядра касательно перерасхода пространства подкачки. Версии ядра ниже 2.6 поддерживали только два значения: 0 и больше нуля. Первое означает, что очевидный перерасход запрещается (при условии использования флага MAP_NORESERVE), а второе разрешает перерасход при любых условиях.