MREMAP(2) | Руководство программиста Linux | MREMAP(2) |
mremap - изменяет отображение адреса виртуальной памяти
#define _GNU_SOURCE /* смотрите feature_test_macros(7) */ #include <sys/mman.h>
void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, ... /* void *new_address */);
Вызов mremap() увеличивает (или уменьшает) размер существующего отображения памяти, при необходимости, перемещая его (это контролируется аргументом flags и доступным виртуальным адресным пространством).
В old_address указывается старый адрес блока виртуальной памяти, который вы хотите изменить. Заметим, что old_address должен быть выровнен по границе страницы. В old_size задаётся старый размер блока виртуальной памяти. В new_size задаётся запрашиваемый размер блока виртуальной памяти после изменения. Описание необязательного пятого аргумента new_address смотрите далее в параграфе о MREMAP_FIXED.
Если значение old_size равно нулю и old_address указывает на общее отображение (смотрите mmap(2) MAP_SHARED), то mremap() создаст новое отображение тех же страниц.Размер нового отображения будет равен значению new_size, а расположение можно указать в new_address; смотрите описание MREMAP_FIXED далее. Если новое отображение запрашивается через этот метод, то также должен быть указан флаг MREMAP_MAYMOVE.
В Linux память делится на страницы. Пользовательскому процессу выделяется один или несколько непрерывных сегментов виртуальной памяти. Каждый из этих сегментов имеет одно или несколько отображений в реальных страницах памяти (в таблице страниц). У каждого виртуального сегмента памяти есть своя защита (права доступа), которые можно нарушить, если произвести попытку некорректного доступа (например, записать информацию в сегмент, который доступен только для чтения). Доступ к виртуальной памяти за пределами сегментов также приводит к ошибке сегментации.
Вызов mremap() использует схему табличных страниц Linux. mremap() изменяет отображение между виртуальными адресами и страницами памяти. Это можно использовать при реализации очень эффективной функции realloc(3).
Аргумент битовой маски flags может быть равен 0 или содержать следующие флаги:
Если сегмент памяти, указанный old_address и old_size, заблокирован (с помощью mlock(2) или подобного вызова), то эта блокировка останется при изменении/перемещении сегмента. Следовательно, количество заблокированной процессом памяти может измениться.
При успешном выполнении mremap() возвращается указатель на новую виртуальную область памяти. При ошибке, возвращается значение MAP_FAILED (то есть (void *) -1), а errno устанавливается в соответствующее значение.
Данный вызов существует только в Linux и не должен использоваться в программах, которые должны быть переносимыми.
До версии 2.4, в glibc не был определён флаг MREMAP_FIXED, а прототип mremap() не позволял указывать аргумент new_address.
Если mremap() используется для перемещения или расширения области, заблокированной mlock(2) или эквивалентом, то вызов mremap() постарается заполнить новую область, но не завершится с ошибкой ENOMEM, если область невозможно заполнить.
До Linux 4.14, если old_size равно нулю и отображение, на которое указывает old_address — частное отображение (mmap(2) MAP_PRIVATE), то вызов mremap() создавал новое частное отображение, не относящееся к первоначальному отображению. Такое поведение не предусматривалось и, вероятно, не ожидается в приложениях пользовательского пространства (так предназначение mremap() — создание нового отображения на основе первоначального). Начиная с Linux 4.14, в этом случае mremap() завершается ошибкой EINVAL.
brk(2), getpagesize(2), getrlimit(2), mlock(2), mmap(2), sbrk(2), malloc(3), realloc(3)
Описание страничной памяти в вашей любимой книге по операционным системам (например, Современные операционные системы Эндрю С. Таненбаума, Внутри Linux Рэндольфа Бентсона, Архитектура операционной системы UNIX Мориса Дж. Баха)
2019-03-06 | Linux |