Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

После заполнения структуры

struct flock
следующим шагом является запрос блокировки. Этот шаг осуществляется с помощью соответствующего значения аргумента
cmd
функции
fcntl
:

F_GETLK
Узнать, можно ли установить блокировку.

F_SETLK
Установить или снять блокировку.

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

Команда

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

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

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

152

Справочная страница GNU/Linux fcntl(3) указывает, что этих сведений может быть недостаточно, процесс может находиться на другой машине! При блокировках по сети есть и другие проблемы, в общем, использование блокировки в файловых системах, смонтированных для удаленных компьютеров, не является удачной мыслью — Примеч. автора.

Команда

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 <sys/file.h> /* XSI */

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

Дескриптор файла

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

153

В системе GNU/Linux

lockf
реализована в виде «оболочки» вокруг
fcntl
Примеч. автора.

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
. Если блокировка доступна, она осуществляется, но если нет, у вас появляется возможность восстановления вместо блокирования в ожидании, возможно, навечно.

154

Тупик (deadlock) является ситуацией, при которой оба процесса блокируются, причем каждый из них ждёт, пока другой освободит определенный ресурс — Примеч. автора.

Завершив работу с заблокированным участком, его следует освободить. Для

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); / * Осуществить блокировку */

/* ...здесь использование заблокированного участка... */

lseek(fd, curpos, SEEK_SET); / * Вернуться к началу блокировки */

lockf(fd, F_ULOCK, len); /* Разблокировать файл */

Если вы не освободите блокировку явным образом, операционная система сделает это за вас в двух случаях. Первый случай, когда процесс завершается (либо при возвращении из

main
, либо с использованием функции
exit
, которую мы рассматривали в разделе 9.1.5.1 «Определение статуса завершения процесса»). Другим случаем является вызов
close
с дескриптором файла: больше об этом в следующем разделе.

Поделиться:
Популярные книги

Император Пограничья 10

Астахов Евгений Евгеньевич
10. Император Пограничья
Фантастика:
городское фэнтези
аниме
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 10

Запечатанный во тьме. Том 3

NikL
3. Хроники Арнея
Фантастика:
уся
эпическая фантастика
фэнтези
5.00
рейтинг книги
Запечатанный во тьме. Том 3

Надуй щеки!

Вишневский Сергей Викторович
1. Чеболь за партой
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Надуй щеки!

#Бояръ-Аниме. Газлайтер. Том 13

Володин Григорий Григорьевич
13. История Телепата
Фантастика:
боевая фантастика
аниме
попаданцы
фэнтези
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 13

Темная сторона. Том 2

Лисина Александра
10. Гибрид
Фантастика:
технофэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Темная сторона. Том 2

Двойник короля 11

Скабер Артемий
11. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 11

Шайтан Иван 3

Тен Эдуард
3. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
7.17
рейтинг книги
Шайтан Иван 3

Мужчина моей судьбы

Ардова Алиса
2. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.03
рейтинг книги
Мужчина моей судьбы

Кодекс Императора III

Сапфир Олег
3. Кодекс Императора
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Императора III

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец

Авалон. Мифический Город

Сказ Алексей
2. Иггдрасиль
Фантастика:
городское фэнтези
рпг
фэнтези
5.00
рейтинг книги
Авалон. Мифический Город

Враг из прошлого тысячелетия

Еслер Андрей
4. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Враг из прошлого тысячелетия

Интриганка

Шелдон Сидни
Приключения:
исторические приключения
9.24
рейтинг книги
Интриганка

Газлайтер. Том 6

Володин Григорий
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6