Читаем Linux программирование в примерах полностью

F_SETLKW  Установить блокировку, подождав, пока это будет возможным.

Команда F_GETLK является командой «Мама, можно мне?» Она осведомляется, доступна ли описанная struct flock блокировка. Если она доступна, блокировка не устанавливается; вместо этого операционная система изменяет поле l_type на F_UNLCK. Другие поля остаются без изменений.

Если блокировка недоступна, операционная система заполняет различные поля сведениями, описывающими уже установленные блокировки, которые препятствуют установке новой. В этом случае l_pid содержит PID процесса, владеющего соответствующей блокировкой.[152] Если блокировка уже установлена, нет другого выбора, кроме ожидания в течение некоторого времени и новой попытки установки блокировки или вывода сообщения об ошибке и отказа от дальнейших попыток.

Команда F_SETLK пытается установить указанную блокировку. Если fcntl() возвращает 0, блокировка была успешно установлена. Если она возвращает -1, блокировку установил другой процесс. В этом случае в errno устанавливается либо EAGAIN (попытайтесь снова позже) или EACCESS (нет доступа). Возможны два значения, чтобы удовлетворить старым системам.

Команда F_SETLKW также пытается установить указанную блокировку. Она отличается от F_SETLK тем, что будет ждать, пока установка блокировки не окажется возможной.

Выбрав соответствующее значение для аргумента cmd, передайте его в качестве второго аргумента fcntl() вместе с указателем на заполненную структуру struct flock в качестве третьего аргумента:

struct flock lock;

 int fd;

 /* ...открыть файл, заполнить struct flock... */

 if (fcntl(fd, F_SETLK, &lock) < 0) {

 /* Установить не удалось, попытаться восстановиться */

}

Функция lockf()[153] предоставляет альтернативный способ установки блокировки в текущем положении файла.

#include /* XSI */

int lockf(int fd, int cmd, off_t len);

Дескриптор файла fd должен быть открыт для записи. len указывает число блокируемых байтов: от текущего положения (назовем его pos) до pos + len байтов, если len положительно, или от pos - len до pos - 1, если len отрицательно. Команды следующие:

F_LOCK   Устанавливает исключительную блокировку диапазона. Вызов блокируется до тех пор, пока блокировка диапазона не станет возможной.

F_TLOCK  Пытается установить блокировку. Это похоже на F_LOCK, но если блокировка недоступна, F_TLOCK возвращает ошибку.

F_ULOCK  Разблокирует указанный раздел. Это может вызвать расщепление блокировки, как описано выше.

F_TEST   Проверяет, доступна ли блокировка. Если доступна, возвращает 0 и устанавливает блокировку. В противном случае возвращает -1 и устанавливает в errno EACCESS.

Возвращаемое значение равно 0 в случае успеха и -1 при ошибке, с соответствующим значением в errno. Возможные значения ошибок включают:

EAGAIN Файл заблокирован, для F_TLOCK или F_TEST.

EDEADLK Для F_TLOCK эта операция создала бы тупик.[154]

ENOLCK Операционная система не смогла выделить блок.

Полезна комбинация F_TLOCK и EDEADLK: если вы знаете, что тупик не может возникнуть никогда, используйте F_LOCK. В противном случае, стоит обезопасить себя и использовать F_TLOCK. Если блокировка доступна, она осуществляется, но если нет, у вас появляется возможность восстановления вместо блокирования в ожидании, возможно, навечно.

Завершив работу с заблокированным участком, его следует освободить. Для fcntl() возьмите первоначальную struct lock, использованную для блокирования, и измените поле l_type на F_UNLCK. Затем используйте F_SETLK в качестве аргумента cmd:

lock.l_whence = ... ; /* Как раньше */

lock.l_start = ... ; /* Как раньше */

lock.l_len = ... ; /* Как раньше */

lock.l_type = F_UNLCK; /* Разблокировать */

if (fcntl(fd, F_SETLK, &lock) < 0) {

 /* обработать ошибку */

}

/* Блокировка была снята */

Код, использующий lockf(), несколько проще. Для краткости мы опустили проверку ошибок:

off_t curpos, len;

curpos = lseek(fd, (off_t)0, SEEK_CUR); /* Получить текущее положение */

len = ... ; / * Установить соответствующее число блокируемых байтов */

lockf(fd, F_LOCK, len); / * Осуществить блокировку */

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

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

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

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