MADVISE(2)

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

ОБЗОР
#include <sys/mman.h>

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

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

madvise(): _BSD_SOURCE

ОПИСАНИЕ
Системный вызов madvise() выдает предложения ядру об использовании постраничного ввода/вывода в диапазоне адресов, начинающегося с addr и размером length байтов. Это позволяет приложению передавать ядру информацию об ожидаемом использовании отображённой или общей области памяти так, чтобы ядро само могло выбрать оптимальный метод упреждающего чтения и технологию кэширования. Этот вызов не влияет на семантику приложения (исключая случай MADV_DONTNEED), но может повлиять на его производительность. Ядро может и проигнорировать эти предложения.

Предложение указывается в аргументе advice; оно может принимать следующие значения:

MADV_NORMAL
    Нет никаких специальных указаний. Используется по умолчанию.

MADV_RANDOM
    Ожидать обращение к страницам в случайном порядке (здесь упреждающее чтение может быть менее эффективным).

MADV_SEQUENTIAL
    Ожидать последовательного обращения к страницам (здесь к страницам в заданном диапазоне можно применить агрессивное упреждающее чтение и быстро высвободить их сразу после доступа).

MADV_WILLNEED
    Ожидать доступа в ближайшем будущем (здесь можно применить упреждающее чтение нескольких страниц).

MADV_DONTNEED
    Не ожидать доступа в ближайшем будущем (в настоящее время приложение завершает работу с данной областью, так что ядро может освободить ресурсы, связываемые с ней). Последующий доступ к страницам в этом диапазоне будет успешным, но приведёт к перезагрузке содержимого памяти из соответствующего отображённого файла (см. mmap(2)) или заполняемых нулями по требованию страниц для отображения без соответствующего файла.

MADV_REMOVE (начиная с Linux 2.6.16)
    Освободить данный диапазон страниц и связанный с ним носитель (backing store). В настоящее время это поддерживается только в файловых системах shmfs/tmpfs; остальные файловые системы возвращают ошибку ENOSYS.

MADV_DONTFORK (начиная с Linux 2.6.16)
    Сделать недоступными страницы в указанном диапазоне для потомка после fork(2). Это полезно для предотвращения изменения физического расположения страницы копирования-при-записи, если родитель будет изменять её после fork(2). (Перемещение таких страниц вызывает проблемы с оборудованием, которые выполняют DMA (прямой доступ к памяти) к этим страницам.)

MADV_DOFORK (начиная с Linux 2.6.16)
    Отменить действие MADV_DONTFORK, восстановить поведение по умолчанию, в силу чего происходит наследование отображения после fork(2).

MADV_HWPOISON (начиная с Linux 2.6.32)
    Испортить страницу и обработать её как будто произошло аппаратное повреждение памяти. Эта операция доступна только для привилегированных (CAP_SYS_ADMIN) процессов. Эта операция может привести к тому, что вызывающий процесс получит сигнал SIGBUS и страница станет неотображённой. Данная возможность предназначена для тестирования кода для обработки ошибок памяти; она доступна, только если ядро было собрано с включённым параметром CONFIG_MEMORY_FAILURE.

MADV_SOFT_OFFLINE (начиная с Linux 2.6.33)
    Программно отключить страницы в диапазоне, указанном addr и length. Память каждой страницы в указанном диапазоне сохраняется (т.е., при следующем доступе будет выдано то же содержимое, но в новых физических границах страницы) и первоначальная страница отключается (т.е., больше не используется и не участвует при обычном управлении памятью). Эффект операции MADV_SOFT_OFFLINE обычно незаметен (т.е., не изменяет семантику) для вызывающего процесса. Данная возможность предназначена для тестирования кода для обработки ошибок памяти; она доступна только, если ядро было собрано с включённым параметром CONFIG_MEMORY_FAILURE.

MADV_MERGEABLE (начиная с Linux 2.6.32)
    Включить слияние одинаковых страниц ядра (Kernel Samepage Merging, KSM) для страниц в диапазоне, указанном addr и length. Ядро периодически сканирует области пользовательской памяти, которые были помечены для слияния, разыскивая станицы с одинаковым содержимым. Такие страницы заменяются единственной страницей, защищённой от записи (которая автоматически копируется, если позднее процесс захочет изменить содержимое страницы). При KSM слияние выполняется только для частных анонимных страниц (см. mmap(2)). Возможность KSM предназначена для приложений, которые генерируют много экземпляров одинаковых данных (например, для систем виртуализации, таких как KVM). Эта возможность может нагрузить процессор; используйте осторожно. Дополнительную информацию можно найти в файле исходного кода ядра Documentation/vm/ksm.txt. Операции MADV_MERGEABLE и MADV_UNMERGEABLE доступны только, если ядро было собрано с включённым параметром CONFIG_KSM.

MADV_UNMERGEABLE (начиная с Linux 2.6.32)
    Отменить действие ранее применённой операции MADV_MERGEABLE для указанного диапазона; KSM разделяет ранее объединённые страницы в диапазоне, заданном addr и length.

MADV_HUGEPAGE (начиная с Linux 2.6.38)
    Включает прозрачность огромных страниц (Transparent Huge Pages, THP) для страниц диапазона, указанного addr и length. В настоящий момент, THP работает только для закрытых (private) анонимных страниц (см. mmap(2)). Ядро будет периодически сканировать области, помеченные как кандидаты в огромные страницы, для замены их огромными страницами. Ядро также будет непосредственно выделять огромные страницы, если область выравнена на размер огромной страницы при создании (naturally) (см. posix_memalign(2)). В основном, эта возможность предназначена для приложений, которые используют большие отображения данных и доступ к большим областям этой памяти за один приём (например, системы виртуализации, такие как QEMU). С её помощью можно очень легко занять память (например, на 2МБ отображение, из которого нужен только 1 байт, будет потрачено 2МБ реальной памяти вместо одной 4КБ страницы). Дополнительную информацию смотрите в файле Documentation/vm/transhuge.txt из исходного кода ядра. Операции MADV_HUGEPAGE и MADV_NOHUGEPAGE доступны, только если при сборке ядра указан параметр CONFIG_TRANSPARENT_HUGEPAGE.

MADV_NOHUGEPAGE (начиная с Linux 2.6.38)
    Проверить, что память адресного пространства, указанного в addr и length, не будет свёрнута в огромные страницы.

MADV_DONTDUMP (начиная с Linux 3.4)
    Исключить из дампа памяти страницы диапазона, задаваемого значениями addr и length. Это полезно в приложениях, которые занимают большие области в памяти, про которые известно, что они ничем не помогут будучи в дампе памяти. Действие MADV_DONTDUMP имеет преимущество над битовой маской, которая устанавливается в файле /proc/PID/coredump_filter (смотрите core(5)).

MADV_DODUMP (начиная с Linux 3.4)
    Отменяет действие, установленное ранее MADV_DONTDUMP.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При нормальном завершении работы madvise() возвращает ноль. При ошибке возвращается -1, а переменной errno присваивается соответствующее значение.

ОШИБКИ

EAGAIN
    Ресурс ядра временно недоступен.

EBADF
    Отображение существует, то область отображения не является файловой.

EINVAL
    Эта ошибка возникает по следующим причинам:

    *   Значение len отрицательно.

    *   Значение addr не выровнено по границе страницы.

    *   Значение advice недопустимо.

    *   Приложение пытается освободить заблокированные или общие страницы (с помощью MADV_DONTNEED).

    *   В advice указано MADV_MERGEABLE или MADV_UNMERGEABLE, но ядро было собрано без параметра CONFIG_KSM.

EIO (для MADV_WILLNEED) Выделение страницы в данной области превысило бы максимальный размер постоянно находящихся в памяти страниц для процесса (rss).

ENOMEM
    (для MADV_WILLNEED) Недостаточно памяти: не удалось выделить страницу

ENOMEM
    Адреса в указанном диапазоне в настоящее время не отображены, или лежит вне адресного пространства процесса.

СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1b. В POSIX.1-2001 описана функция posix_madvise(3) с константами POSIX_MADV_NORMAL и т.д., и её поведение похоже на описываемое здесь. Для файлового доступа есть похожий вызов posix_fadvise(2). MADV_REMOVE, MADV_DONTFORK, MADV_DOFORK, MADV_HWPOISON, MADV_MERGEABLE и MADV_UNMERGEABLE есть только в Linux.

ЗАМЕЧАНИЯ

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

Системный вызов текущей реализации (2.4.0) в Linux больше похож на команду, которая предлагает, и следовательно может завершиться с ошибкой, если невозможно сделать то, что предлагается. (Смотрите раздел ОШИБКИ выше.) Это нестандартное поведение.

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

СМОТРИТЕ ТАКЖЕ
getrlimit(2), mincore(2), mmap(2), mprotect(2), msync(2), munmap(2), core(5)