В 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()
разблокирует страницы, подпадающие под его влияние.
13.3. Блокирование файлов
Хотя доступ к одному и тому же файлу со стороны нескольких процессов — вполне обычное явление, делать это следует осторожно. Многие файлы содержат сложные структуры данных, и обновление этих структур создает те же условия состязаний, что и в обработчиках сигналов и областях совместно используемой памяти.
Существует два типа блокирования файлов. Наиболее распространенное — рекомендательное блокирование, которое ядром принудительно не осуществляется. Это просто соглашение, которому должны следовать все процессы, имеющие доступ к файлу. Второй тип, обязательное блокирование, принудительно выполняется ядром. Когда процесс блокирует файл для записи, другие процессы, пытающиеся прочитать или записать в файл, приостанавливаются до снятия блокировки. Хотя этот метод может показаться более очевидным, обязательное блокирование вынуждает ядро совершать проверку наличия блокировок при каждом вызове read()
и write()
, существенно снижая производительность этих системных вызовов.
Операционная система Linux предоставляет два метода блокирования файлов: блокировочные файлы и блокирование записей.
13.3.1. Блокировочные файлы
Блокировочные файлыявляются наиболее простым методом блокирования. Каждый нуждающийся в блокировании файл данных ассоциируется с блокировочным файлом. Когда блокировочный файл существует, файл данных считается заблокированным, и другие процессы не имеют к нему доступа. Когда блокировочный файл не существует, процесс создает его и затем получает доступ к файлу данных. До тех пор, пока процедура создания блокировочного файла атомарна (только один процесс за раз может "владеть" блокировочным файлом), этот метод гарантирует доступ к файлу со стороны только одного процесса в каждый момент времени.
Читать дальше