Вход/Регистрация
UNIX: взаимодействие процессов
вернуться

Стивенс Уильям Ричард

Шрифт:

Структура flock описывает тип блокировки (чтение или запись) и блокируемый диапазон. Как и в 1 seek, начальный сдвиг представляет собой сдвиг относительно начала файла, текущего положения или конца файла, и интерпретируется в зависимости от значения поля l_whence (SEEK_SET, SEEK_CUR, SEEK_END).

Поле l_len указывает длину блокируемого диапазона. Значение 0 соответствует блокированию от l_start до конца файла. Существуют, таким образом, два способа заблокировать файл целиком:

1. Указать l_whence = SEEK_SET, l_start = 0 и l_len = 0.

2. Перейти к началу файла с помощью lseek, затем указать l_whence = SEEK_CUR, l_start = 0 и l_len = 0.

Чаще всего используется первый метод, поскольку он предусматривает единственный вызов (fcntl — см. также упражнение 9.10).

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

Все блокировки, установленные конкретным процессом, снимаются при закрытии дескриптора файла этим процессом и при завершении его работы. Блокировки не наследуются дочерним процессом при вызове fork.

ПРИМЕЧАНИЕ

Снятие блокировок при завершении процесса обеспечивается только для блокировок записей fcntl и (в качестве дополнительной возможности) для семафоров System V. Для других средств синхронизации (взаимных исключений, условных переменных, блокировок чтения-записи и семафоров Posix) автоматическое снятие при завершении процесса не предусматривается. Об этом мы говорили в конце раздела 7.7. 

Блокировка записей не должна использоваться со стандартной библиотекой ввода-вывода, поскольку функции из этой библиотеки осуществляют внутреннюю буферизацию. С заблокированными файлами следует использовать функции read и write, чтобы не возникало неожиданных проблем. 

Пример

Вернемся к нашему примеру из листинга 9.2 и перепишем функции my_lock и my_unlock из листинга 9.1 так, чтобы воспользоваться блокировкой записей Posix. Текст этих функций приведен в листинге 9.3.

Листинг 9.3. Блокировка записей fcntl по стандарту Posix

//lock/lockfcntl.c

1 #include "unpipc.h"

2 void

3 my_lock(int fd)

4 {

5 struct flock lock;

6 lock.l_type = F_WRLCK;

7 lock.l_whence = SEEK_SET;

8 lock.l_start = 0;

9 lock.l_len = 0; /* блокирование всего файла на запись */

10 Fcntl(fd, F_SETLKW, &lock);

11 }

12 void

13 my_unlock(int fd)

14 {

15 struct flock lock;

16 lock.l_type = F_UNLCK;

17 lock.l_whence = SEEK_SET;

18 lock.l_start = 0;

19 lock.l_len = 0; /* разблокирование всего файла */

20 Fcntl(fd. F_SETLK, &lock);

21 }

Обратите внимание, что мы устанавливаем блокировку на запись, что гарантирует единственность изменяющего данные процесса (см. упражнение 9.4). При получении блокировки мы используем команду F_SETLKW, чтобы приостановить выполнение процесса при невозможности установки блокировки.

ПРИМЕЧАНИЕ

Зная определение структуры flock, приведенное выше, мы могли бы проинициализировать структуру my_lock как

static struct flock lock = { F_WRLCK, SEEK_SET, 0, 0, 0 };

но это неверно. Posix определяет только обязательные поля структуры, а реализации могут менять их порядок и добавлять к ним дополнительные.

Мы не приводим результат работы пpoгрaммы, но она, судя по всему, работает правильно. Выполнение этой программы не дает возможности утверждать, что в ней нет ошибок. Если результат оказывается неправильным, то можно сказать с уверенностью, что что-то не так. Но успешное выполнение программы еще ни о чем не говорит. Ядро могло выполнить сначала одну программу, затем другую, и если они не выполнялись параллельно, мы не имеем возможности увидеть ошибку. Увеличить шансы обнаружения ошибки можно, изменив функцию main таким образом, чтобы последовательный номер увеличивался 10000 раз, и запустив 20 экземпляров программы одновременно. Если начальное значение последовательного номера в файле было 1, мы можем ожидать, что после завершения работы всех этих процессов мы увидим в файле число 200001.

  • Читать дальше
  • 1
  • ...
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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