фактически блокирует все страницы между страницей, содержащей первый адрес, и страницей, содержащей последний адрес, включительно. После завершения mlock() все страницы, на которые распространился вызов, окажутся в ОЗУ.

Если процессу необходимо заблокировать все свое адресное пространство, применяется mlосkall(). Аргумент flags принимает значение одного или обоих описанных ниже флагов, объединенных с помощью битового 'ИЛИ'.

MCL_CURRENT Все страницы, в данный момент находящиеся в адресном пространстве процесса, блокируются в ОЗУ. После завершения вызова mlockall() они все будут в ОЗУ.
MCL_FUTURE Все страницы, добавленные к адресному пространству процесса, будут заблокированы в ОЗУ.

Разблокирование памяти — это почти то же, что ее блокирование. Если процесс больше не нуждается в блокировании памяти, munlockall() разблокирует все его страницы. munlock() принимает те же аргументы, что и mlock(), и разблокирует страницы, относящиеся к указанной области.

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

13.3. Блокирование файлов

Хотя доступ к одному и тому же файлу со стороны нескольких процессов — вполне обычное явление, делать это следует осторожно. Многие файлы содержат сложные структуры данных, и обновление этих структур создает те же условия состязаний, что и в обработчиках сигналов и областях совместно используемой памяти.

Существует два типа блокирования файлов. Наиболее распространенное — рекомендательное блокирование, которое ядром принудительно не осуществляется. Это просто соглашение, которому должны следовать все процессы, имеющие доступ к файлу. Второй тип, обязательное блокирование, принудительно выполняется ядром. Когда процесс блокирует файл для записи, другие процессы, пытающиеся прочитать или записать в файл, приостанавливаются до снятия блокировки. Хотя этот метод может показаться более очевидным, обязательное блокирование вынуждает ядро совершать проверку наличия блокировок при каждом вызове read() и write(), существенно снижая производительность этих системных вызовов.

Операционная система Linux предоставляет два метода блокирования файлов: блокировочные файлы и блокирование записей.

13.3.1. Блокировочные файлы

Блокировочные файлы являются наиболее простым методом блокирования. Каждый нуждающийся в блокировании файл данных ассоциируется с блокировочным файлом. Когда блокировочный файл существует, файл данных считается заблокированным, и другие процессы не имеют к нему доступа. Когда блокировочный файл не существует, процесс создает его и затем получает доступ к файлу данных. До тех пор, пока процедура создания блокировочного файла атомарна (только один процесс за раз может 'владеть' блокировочным файлом), этот метод гарантирует доступ к файлу со стороны только одного процесса в каждый момент времени.

Идея довольно проста. Когда процесс намеревается получить доступ к файлу, он блокирует файл следующим образом.

fd = open('somefile.lck', O_RDONLY, 0644);

if (fd >= 0) {

 close(fd);

 printf('файл уже заблокирован');

 return 1;

} else {

 /* блокировочный файл не существует, мы можем заблокировать его

    и получить доступ */

 fd = open('somefile.lck', O_CREAT | O_WRONLY, 0644');

 if (fd < 0) {

  perror('ошибка при создании блокировочного файла');

  return 1;

 }

 /* можем записать pid в файл */

 close(fd);

}

Когда процесс заканчивает обработку файла, он вызывает unlink('somefile.lck') для снятия блокировки.

Несмотря на то что показанный выше фрагмент кода выглядит корректным, он позволяет при некоторых обстоятельствах нескольким процессам блокировать один файл, а именно этого и следует избегать в блокировании. Если процесс проверяет существование блокировочного файла, убеждается в том, что блокировочный файл не существует, и прерывается ядром, чтобы позволить выполняться прочим процессам, то какой-то другой процесс сможет заблокировать файл до того, как исходный процесс создаст блокировочный файл. Флаг O_EXCL для open() может сделать создание блокировочного файла атомарным и, следовательно, защищенным от условия состязаний. После установки O_EXCL вызов open() завершается неудачей, если файл уже существует. Это упрощает создание блокировочных файлов, которое происходит так, как показано ниже.

fd = open('somefile.lck', O_WRONLY | O_CREAT | O_EXCL, 0644);

if (fd < 0 && errno == EEXIST) {

 printf('файл уже заблокирован');

 return 1;

} else if (fd < 0) {

 perror('непредвиденная ошибка при проверке блокировки');

 return 1;

}

/* можем записать pid в файл */

close(fd);

Блокировочные файлы используются для блокирования широкого ряда стандартных файлов Linux,

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату