13.2.5. Блокировка областей памяти

13.2.5. Блокировка областей памяти

В Linux и многих других современных операционных системах для областей памяти можно организовать страничный обмен с диском (или отклонять, если их невозможно заменить каким-либо другим способом), когда возникает дефицит памяти. На приложения, чувствительные к ограничениям внешней синхронизации, может неблагоприятно повлиять задержка, к которой приводит подкачка страниц обратно в ОЗУ, когда это необходимо процессу. Для улучшения надежности таких приложений Linux позволяет процессу блокировать области памяти в ОЗУ, чтобы сделать эти синхронизации более предсказуемыми. В целях безопасности блокировка памяти разрешена только процессам с полномочиями привилегированного пользователя[87]. Если блокировать области памяти сможет любой процесс, то какой-то неисправный процесс может заблокировать все ОЗУ системы и привести ее к краху. Общее количество памяти, блокируемой процессом, не может превышать предел использования RLIMIT_MEMLOCK (см. главу 10).

Для блокирования и разблокирования областей памяти применяются перечисленные ниже вызовы.

#include <sys/mman.h>

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() разблокирует страницы, подпадающие под его влияние.