MS_ASYNC | Модифицированные версии области памяти запланированы на "скорую" синхронизацию. Использовать можно только либо MS_ASYNC , либо MS_SYNC . |
MS_SYNC | Модифицированные страницы в области памяти записываются на диск до возврата системного вызова msync() . Использовать можно только либо MS_ASYNC , либо MS_SYNC . |
MS_INVALIDATE | Эта опция позволяет ядру выяснять, записываются ли изменения на диск. Хотя эта опция не дает гарантию того, что они не будут записаны, она сообщает ядру, что необходимость сохранения изменений отсутствует. Этот флаг применяется только при особых условиях. |
0 | Передача 0 в msync() работает в ядрах Linux, хотя она не очень хорошо документирована. Она похожа на MS_ASYNC , но означает, что страницы должны записываться на диск при любом удобном случае. Обычно это значит, что они будут сбрасываться на диск при каждом следующем запуске потока ядра bdflush (обычно он запускается каждые 30 секунд), в то время как MS_ASYNC записывает страницы более интенсивно. |
В Linux и многих других современных операционных системах для областей памяти можно организовать страничный обмен с диском (или отклонять, если их невозможно заменить каким-либо другим способом), когда возникает дефицит памяти. На приложения, чувствительные к ограничениям внешней синхронизации, может неблагоприятно повлиять задержка, к которой приводит подкачка страниц обратно в ОЗУ, когда это необходимо процессу. Для улучшения надежности таких приложений Linux позволяет процессу блокировать области памяти в ОЗУ, чтобы сделать эти синхронизации более предсказуемыми. В целях безопасности блокировка памяти разрешена только процессам с полномочиями привилегированного пользователя[87]. Если блокировать области памяти сможет любой процесс, то какой-то неисправный процесс может заблокировать все ОЗУ системы и привести ее к краху. Общее количество памяти, блокируемой процессом, не может превышать предел использования RLIMIT_MEMLOCK
(см. главу 10).
Для блокирования и разблокирования областей памяти применяются перечисленные ниже вызовы.
#include
int mlock(caddr_t addr, size_t length);
int mlockall(int flags);
int munlock(caddr_t addr, size_t length);
int munlockall(void);
Первый вызов, mlock()
, блокирует length
байт, начиная с адреса addr
. За один раз должна блокироваться полная страница памяти, поэтому mlock()
фактически блокирует все страницы между страницей, содержащей первый адрес, и страницей, содержащей последний адрес, включительно. После завершения mlock()
все страницы, на которые распространился вызов, окажутся в ОЗУ.
Если процессу необходимо заблокировать все свое адресное пространство, применяется mlосkall()
. Аргумент flags
принимает значение одного или обоих описанных ниже флагов, объединенных с помощью битового "ИЛИ".
MCL_CURRENT | Все страницы, в данный момент находящиеся в адресном пространстве процесса, блокируются в ОЗУ. После завершения вызова mlockall() они все будут в ОЗУ. |
MCL_FUTURE | Все страницы, добавленные к адресному пространству процесса, будут заблокированы в ОЗУ. |
Разблокирование памяти — это почти то же, что ее блокирование. Если процесс больше не нуждается в блокировании памяти, munlockall()
разблокирует все его страницы. munlock()
принимает те же аргументы, что и mlock()
, и разблокирует страницы, относящиеся к указанной области.
Многократное блокирование страницы эквивалентно однократному. В каждом случае отдельный вызов munlock()
разблокирует страницы, подпадающие под его влияние.