Читаем Linux API. Исчерпывающее руководство полностью

Как показано в табл. 51.1, файловую блокировку можно снять, задействуя вызов flock(), указав в качестве аргумента operation флаг LOCK_UN. Кроме того, блокировка будет автоматически снята при закрытии соответствующего файлового дескриптора. Однако не все так просто. Блокировка, полученная с помощью вызова flock(), связана с описанием открытого файла (см. раздел 5.4), а не с его дескриптором или самим файлом (индексным дескриптором файла). Это значит, что при дублировании файлового дескриптора (используя вызовы dup() и dup2() или вызов fcntl() с флагом F_DUPFD) его копия будет ссылаться на ту же блокировку. Например, при полученной блокировке файла, на который указывает аргумент fd, для ее снятия потребуется следующий код (проверка на ошибки опускается):

flock(fd, LOCK_EX); /* Получаем блокировку с помощью 'fd'*/

newfd = dup(fd); /* 'newfd' ссылается на ту же блокировку, что и 'fd' */

flock(newfd, LOCK_UN); /* Снимаем блокировку, полученную с помощью 'fd' */

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

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

fd1 = open("a.txt", O_RDWR);

fd2 = open("a.txt", O_RDWR);

flock(fd1, LOCK_EX);

flock(fd2, LOCK_EX); /* Исключается из-за блокировки, установленной для 'fd1' */

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

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

flock(fd, LOCK_EX); /* Родитель получает блокировку */

if (fork() == 0) /* Если это потомок… */

flock(fd, LOCK_UN); /* Снимаем блокировку, разделяемую с родителем */

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

Блокировки, созданные с применением flock(), сохраняются на протяжении всей работы вызова exec() (разве что на описание открытого файла ссылается единственный дескриптор, для которого установлен флаг FD_CLOEXEC).

Семантика, описанная выше, применяется в Linux и соответствует классической реализации вызова flock() в системах BSD. В некоторых UNIX-системах вызов flock() основан на fcntl(); позже вы увидите, что поведение этих вызовов при наследовании и снятии блокировок отличается. Поскольку взаимодействие блокировок, созданных с помощью вызовов flock() и fcntl(), является неопределенным, для каждого конкретного файла блокировки следует создавать каким-то одним способом.

51.2.2. Ограничения вызова flock()

Создание блокировок с использованием вызова flock() имеет несколько ограничений.

• Файлы можно блокировать только целиком. Такая грубая блокировка может негативно сказаться на параллельной работе взаимодействующих процессов. Например, если их несколько и все хотят получить доступ к разным участкам одного файла, то теоретически они могут работать параллельно, однако вызов flock() исключил бы такую возможность.

• Вызов flock() позволяет устанавливать только необязательные блокировки.

• Многие реализации файловой системы NFS не распознают блокировки, выданные вызовом flock().

Вызов fcntl(), который мы рассмотрим в следующем разделе, реализует модель, лишенную этих ограничений.

51.3. Блокировка записей с помощью вызова fcntl()

Используя вызов fcntl() (см. раздел 5.2), блокировку можно установить как для всего файла целиком, так и для любой его части, даже если ее размер равен одному байту. Такой подход обычно называют блокировкой записей, хотя это не совсем верно, поскольку файлы в UNIX-системе не имеют границ (присущих записям) и представляют собой байтовые последовательности. Понятие записи в случае с файлом определяется исключительно самим приложением.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных