Scroll to navigation

MADVISE(2) Руководство программиста Linux MADVISE(2)

ИМЯ

madvise - отсылает предложения по использованию памяти

СИНТАКСИС

#include <sys/mman.h>

int madvise(void *addr, size_t length, int advice);

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

madvise():

Начиная с glibc 2.19:
_DEFAULT_SOURCE
Начиная с glibc 2.19:
_BSD_SOURCE

ОПИСАНИЕ

Системный вызов madvise() используется, чтобы дать совет или указать направление ядру о диапазоне адресов, начинающемся с адреса addr и имеющем размер length байт. В большинстве случаев, целью такого совета является повышение производительности системы или приложения.

Первоначально, системный вызов поддерживал набор «стандартных» значений advice, которые также доступны и в некоторых других реализациях (однако отметим, что madvise() отсутствует в POSIX). В последствии было добавлено несколько значений advice, имеющихся только в Linux.

Стандартные значения предложений

Значения advice, перечисленные далее, позволяют приложению указать ядру как оно будет использовать некоторые отображённые или общие области памяти, чтобы ядро могло выбрать подходящие методы упреждающего чтения и кэширования. Эти значения advice не влияют на семантику приложения (за исключением MADV_DONTNEED), но могут повлиять на его производительность. Все перечисленные здесь значения advice имеют аналоги в определённой POSIX функции posix_madvise(3) и имеют тот же смысл, за исключением MADV_DONTNEED.

В advice помещается нужное предложения, одно из:

Нет никаких специальных указаний. Используется по умолчанию.
Ожидать обращение к страницам в случайном порядке (здесь упреждающее чтение может быть менее эффективным).
Ожидать последовательного обращения к страницам (здесь к страницам в заданном диапазоне можно применить агрессивное упреждающее чтение и быстро высвободить их сразу после доступа).
Ожидать доступа в ближайшем будущем (здесь можно применить упреждающее чтение нескольких страниц).
В ближайшем будущем не ожидается доступ (в настоящее время приложение закончило работу с данным диапазоном, поэтому ядро может освободить ресурсы, связанные с приложением).
После успешного выполнения операции MADV_DONTNEED семантика доступа к памяти в заданной области изменяется: последующий доступ к страницам в области будет успешным, но будет приводить к или повторному заполнению памяти актуальным содержимым из нижележащего отображённого файла (для общих отображений файла, общих анонимных отображений и методов на основе shmem, таких как сегментов общей памяти System V) или к заполнению нулями страниц по требованию у частных анонимных отображений.
Заметим, что при применении к общим отображениям операция MADV_DONTNEED может не приводить к немедленному освобождению страниц области. Ядро может задержать освобождение до подходящего момента. Однако размер постоянно занимаемой памяти (RSS) вызывающего процесса будет сокращён сразу же.
Операция MADV_DONTNEED не может применяться к заблокированным страницам, страницам Huge TLB или страницам VM_PFNMAP (страницы, помеченные внутренним флагом ядра VM_PFNMAP представляют собой специальные области памяти, которые не управляются из подсистемы виртуальной памяти; обычно, эти страницы создаются драйверами устройств, которые отображают страницы в пользовательское пространство).

Значения предложений, имеющиеся только в Linux

Следующие значения advice имеются только в Linux и не имеют аналога в определённой POSIX функции posix_madvise(3), а также могут не иметь аналога и в других реализациях интерфейса madvise(). Заметим, что некоторые из этих операций изменяют семантику доступа к памяти.

Освободить указанный диапазон страниц и связанные с ним хранилища. Эквивалентен пробивке отверстия в соответствующем диапазоне байт хранилища (смотрите fallocate(2)). Последующий доступ к указанному адресному диапазону будет возвращать байты с нулями.
Указываемый адресный диапазон должен быть общим и доступным на запись отображением. Этот флаг не может применять к заблокированным страницам, страницам Huge TLB или страницам VM_PFNMAP.
В первоначальной реализации MADV_REMOVE поддерживался только в tmpfs(5), но начиная с Linux 3.5 все файловые системы, поддерживающие fallocate(2) с режимом FALLOC_FL_PUNCH_HOLE, также поддерживают MADV_REMOVE. Hugetlbfs возвращает ошибку EINVAL, а другие файловые системы возвращают ошибку EOPNOTSUPP.
Сделать недоступными страницы в указанном диапазоне для потомка после fork(2). Это полезно для предотвращения изменения физического расположения страницы копирования-при-записи, если родитель будет изменять её после fork(2) (перемещение таких страниц вызывает проблемы для оборудования, обращающегося к страницам через DMA).
Отменить действие MADV_DONTFORK, восстановить поведение по умолчанию, в силу чего происходит наследование отображения после fork(2).
Испортить страницы в диапазоне, заданном addr и length, и обрабатывать последующие ссылки на эти страницы как при аппаратном повреждении памяти. Данная операция доступна только для привилегированных (CAP_SYS_ADMIN) процессов. Она может привести к тому, что вызывающий процесс получит SIGBUS и отображение страницы удалится.
Это свойство предназначено для тестирования кода обработки ошибок памяти; оно доступно только, если ядро было собрано с параметром CONFIG_MEMORY_FAILURE.
Включает слияние одинаковых страниц ядра (Kernel Samepage Merging, KSM) для страниц в диапазоне, указанном addr и length. Ядро периодически сканирует области пользовательской памяти, которые были помечены для слияния, разыскивая станицы с одинаковым содержимым. Такие страницы заменяются единственной страницей, защищённой от записи (которая автоматически копируется, если позднее процесс захочет изменить содержимое страницы). При KSM слияние выполняется только для частных анонимных страниц (смотрите mmap(2)).
Возможность KSM предназначена для приложений, которые генерируют много экземпляров одинаковых данных (например, для систем виртуализации, таких как KVM). Эта возможность может нагрузить процессор; используйте осторожно. Дополнительную информацию можно найти в файле исходного кода ядра Documentation/admin-guide/mm/ksm.rst.
Операции MADV_MERGEABLE и MADV_UNMERGEABLE доступны только, если ядро собрано с параметром CONFIG_KSM.
Отменить действие ранее применённой операции MADV_MERGEABLE для указанного диапазона; KSM разделяет ранее объединённые страницы в диапазоне, заданном addr и length.
Программно отключить страницы в диапазоне, указанном addr и length. Память каждой страницы в указанном диапазоне сохраняется (т. е., при следующем доступе будет выдано то же содержимое, но в новых физических границах страницы) и первоначальная страница отключается (т. е., больше не используется и не участвует при обычном управлении памятью). Эффект операции MADV_SOFT_OFFLINE обычно незаметен (т. е., не изменяет семантику) для вызывающего процесса.
Это свойство предназначено для тестирования кода обработки ошибок памяти; оно доступно только, если ядро было собрано с параметром CONFIG_MEMORY_FAILURE.
Включает прозрачность огромных страниц (Transparent Huge Pages, THP) для страниц в диапазоне, указанном addr и length. В настоящий момент, THP работает только для закрытых (private) анонимных страниц (смотрите mmap(2)). Ядро будет периодически сканировать области, помеченные как кандидаты в огромные страницы, для замены их огромными страницами. Ядро также будет непосредственно выделять огромные страницы, если область выравнена на аппаратный (naturally) размер огромной страницы при создании (смотрите posix_memalign(2)).
В основном, эта возможность предназначена для приложений, которые используют большие отображения данных и доступ к большим областям этой памяти за один приём (например, системы виртуализации, такие как QEMU). С её помощью можно очень легко занять память (например, на 2 МБ отображение, из которого нужен только 1 байт, будет потрачено 2 МБ реальной памяти вместо одной 4 КБ страницы). Дополнительную информацию смотрите в файле Documentation/admin-guide/mm/transhuge.rst из исходного кода ядра.
Most common kernels configurations provide MADV_HUGEPAGE-style behavior by default, and thus MADV_HUGEPAGE is normally not necessary. It is mostly intended for embedded systems, where MADV_HUGEPAGE-style behavior may not be enabled by default in the kernel. On such systems, this flag can be used in order to selectively enable THP. Whenever MADV_HUGEPAGE is used, it should always be in regions of memory with an access pattern that the developer knows in advance won't risk to increase the memory footprint of the application when transparent hugepages are enabled.
Операции MADV_HUGEPAGE и MADV_NOHUGEPAGE доступны только, если ядро собрано с параметром CONFIG_TRANSPARENT_HUGEPAGE.
Ensures that memory in the address range specified by addr and length will not be backed by transparent hugepages.
Исключить из дампа памяти страницы диапазона, задаваемого значениями addr и length. Это полезно в приложениях, которые занимают большие области в памяти, про которые известно, что они ничем не помогут будучи в дампе памяти. Действие MADV_DONTDUMP имеет преимущество над битовой маской, которая устанавливается в файле /proc/[pid]/coredump_filter (смотрите core(5)).
Отменяет действие, установленное ранее MADV_DONTDUMP.
Приложению больше не требуются страницы в диапазоне, задаваемом addr и len, поэтому ядро может освободить эти страницы, но освобождение может быть отложено до тех пор, пока не понадобится память. Для каждой страницы, помеченной как свободная, но ещё не освобождённая, операция освобождения будет отменена, если вызывающий выполнит запись в эту страницу. После успешного выполнения операции MADV_FREE все повисшие данные (т. е., изменённые (dirty) и не записанные страницы) будут потеряны в момент освобождения страниц ядром. Однако последующая запись в страницы в этом диапазоне будет успешной и поэтому ядро не сможет освободить эти изменённые страницы и вызывающий всегда может видеть только что записанные данные. Если последующей записи не было, то ядро может освободить страницы в любой момент. После освобождения страниц диапазона при последующем доступе вызывающий может видеть страницы заполненные нулями по требованию.
Операция MADV_FREE может применяться только при частным анонимным страницам (смотрите mmap(2)). В Linux до версии 4.12 страницы задаваемого диапазона в системе без подкачки освобождаются сразу, независимо от необходимости в памяти.
Выдать дочернему процессу заполненную нулями память в этом диапазоне после fork(2). Это позволяет при ветвлении (forking) серверов стереть важные данные процесса (например, начальные значения PRNG, данные шифрования и т. п.) у дочерних процессов.
Операция MADV_WIPEONFORK применима только к частным анонимным страницам (смотрите mmap(2)).
В потомке, созданном fork(2), значение MADV_WIPEONFORK остаётся у указанного адресного диапазона. Это значение стирается при execve(2).
Отменяет действие, установленное ранее MADV_WIPEONFORK.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При нормальном завершении работы madvise() возвращает ноль. При ошибке возвращается -1, а переменной errno присваивается соответствующее значение.

ОШИБКИ

В advice указан MADV_REMOVE, но описанный диапазон адресов не является общей памятью с разрешением на записи
Ресурс ядра временно недоступен.
Отображение существует, то область отображения не является файловой.
Значение параметра addr не выровнено по границе страницы или параметр length содержит отрицательное число.
Значение advice недопустимо.
Значение advice равно MADV_DONTNEED или MADV_REMOVE, а указанный адресный диапазон включает заблокированные, Huge TLB или VM_PFNMAP страницы.
Значение advice равно MADV_MERGEABLE или MADV_UNMERGEABLE, но ядро было собрано без параметра CONFIG_KSM.
Значение advice равно MADV_FREE или MADV_WIPEONFORK, но в указанном адресном диапазоне содержится файл, Huge TLB, диапазоны MAP_SHARED или VM_PFNMAP.
(для MADV_WILLNEED) Выделение страницы в данной области превысило бы максимальный размер постоянно находящихся в памяти страниц для процесса (rss).
(для MADV_WILLNEED) Недостаточно памяти: не удалось выделить страницу
Адреса в указанном диапазоне в настоящее время не отображены, или лежит вне адресного пространства процесса.
В переменной advice содержится MADV_HWPOISON, но вызывающий не имеет мандата CAP_SYS_ADMIN.

ВЕРСИИ

Начиная с Linux 3.18 поддержка данного системного вызова необязательна, она зависит от того, собрано ли ядро с параметром CONFIG_ADVISE_SYSCALLS.

СООТВЕТСТВИЕ СТАНДАРТАМ

Вызов madvise() не включён ни в один стандарт. Версии этого системного вызова, реализующие широкий набор значений advice, существуют во многих других системах. В них, обычно, реализуются, как минимум, флаги перечисленные в Стандартные значения предложений, хотя и с некоторыми различиями в семантике.

В POSIX-2001 описана функция posix_madvise(3) с константами POSIX_MADV_NORMAL, POSIX_MADV_RANDOM, POSIX_MADV_SEQUENTIAL, POSIX_MADV_WILLNEED и POSIX_MADV_DONTNEED, и т. п., реализующая поведение близкое к флагам с именами, перечисленным выше.

ЗАМЕЧАНИЯ

Замечания, касающиеся Linux

Для реализации Linux требуется, чтобы адрес addr был выровнен на границу страницы, а значение length может быть нулевым. Если какие-то части указанного адресного диапазона не отображены, то версия Linux madvise() игнорирует их и вызов применяется к оставшейся области (но возвращается значение ENOMEM, как и должно).

СМ. ТАКЖЕ

getrlimit(2), mincore(2), mmap(2), mprotect(2), msync(2), munmap(2), prctl(2), posix_madvise(3), core(5)

ЗАМЕЧАНИЯ

Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.

ПЕРЕВОД

Русский перевод этой страницы руководства был сделан aereiae <aereiae@gmail.com>, Alexey <a.chepugov@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, ITriskTI <ITriskTI@gmail.com>, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com> и Малянов Евгений Викторович <maljanow@outlook.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.

11 апреля 2020 г. Linux