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

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

Жанры

UNIX: взаимодействие процессов

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

Шрифт:
Листинг 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.

Пример: упрощение с помощью макросов

В листинге 9.3 установка и снятие блокировки занимали шесть строк кода. Мы должны выделить место под структуру, инициализировать ее и затем вызвать fcntl. Программы можно упростить, если определить следующие семь макросов, которые взяты из раздела 12.3 [21]:

#define read_lock(fd, offset, whence, len) \

 lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)

#define readw_lock(fd, offset, whence, len) \

 lock_reg(fd, F_SETLKW, F_RDlCK, offset, whence, len)

#define write_lock(fd, offset, whence, len) \

 lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)

#define writew_lock(fd, offset, whence, len) \

 lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len)

#define un_lock(fd, offset, whence, len) \

 lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)

#define is_read_lockable(fd, offset, whence, len) \

 lock_test(fd, F_RDLCK, offset, whence, len)

#define is_write_lockable(fd, offset, whence, len) \

 lock_test(fd, F_WRLCK, offset, whence, len)

Эти макросы используют наши функции lock_reg и lock_test, текст которых приведен в листингах 9.4 и 9.5. С ними нам уже не нужно заботиться об инициализации структур и вызове функций. Первые три аргумента специально сделаны совпадающими с первыми тремя аргументами функции lseek.

Мы также определяем две функции-обертки, Lock_reg и Lock_test, завершающие свое выполнение с возвратом ошибки fcntl, и семь макросов с именами, начинающимися с заглавной буквы, чтобы эти функции вызывать.

С помощью новых макросов мы можем записать функции my_lock и my_unlock из листинга 9.3 как

#define my_lock(fd) (Writew_lock(fd, 0, SEEK_SET, 0))

#define my_unlock(fd) (Un_lock(fd, 0, SEEK_SET, 0))

Листинг 9.4. Вызов fcntl для получения и снятия блокировки

//lib/lock_reg.c

1 #include "unpipc.h"

2 int

3 lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)

4 {

5 struct flock lock;

6 lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */

7 lock.l_start = offset; /* сдвиг по отношению к l_whence */

8 lock.l_whence = whence; /* SEEK SET. SEEK CUR, SEEK END */

9 lock.l_len = len; /* количество байтов (0 – до конца файла) */

10 return(fcnt(fd, cmd, &lock)"); /* –1 в случае ошибки */

11 }

Листинг 9.5. Вызов fcntl для проверки состояния блокировки

//lib/lock_test.c

1 #include "unpipc.h"

2 pid_t

3 lock_test(int fd, int type, off_t offset, int whence, off_t len)

4 {

5 struct flock lock;

6 lock.l_type = type; /* F_RDLCK or F_WRLCK */

7 lock.l_start = offset; /* сдвиг по отношению к l_whence */

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

Бастард Императора. Том 14

Орлов Андрей Юрьевич
14. Бастард Императора
Фантастика:
городское фэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Бастард Императора. Том 14

Он тебя не любит(?)

Тоцка Тала
Любовные романы:
современные любовные романы
7.46
рейтинг книги
Он тебя не любит(?)

Последний Паладин. Том 10

Саваровский Роман
10. Путь Паладина
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Последний Паладин. Том 10

Ермак. Противостояние. Книга одиннадцатая

Валериев Игорь
11. Ермак
Фантастика:
попаданцы
альтернативная история
4.50
рейтинг книги
Ермак. Противостояние. Книга одиннадцатая

Отморозок 1

Поповский Андрей Владимирович
1. Отморозок
Фантастика:
попаданцы
5.00
рейтинг книги
Отморозок 1

Метатель

Тарасов Ник
1. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель

Начало шторма

Мазуров Дмитрий
9. Громовая поступь
Фантастика:
фэнтези
рпг
5.75
рейтинг книги
Начало шторма

Идеальный мир для Лекаря 17

Сапфир Олег
17. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 17

Месть Паладина

Юллем Евгений
5. Псевдоним `Испанец`
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Месть Паладина

Лекарь Империи 3

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

Последний Паладин. Том 5

Саваровский Роман
5. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 5

Пламенев. Книга 3-7

Карелин Сергей Витальевич
Пламенев
Фантастика:
аниме
уся
фэнтези
сянься
5.00
рейтинг книги
Пламенев. Книга 3-7

Солдат Империи

Земляной Андрей Борисович
1. Страж
Фантастика:
попаданцы
альтернативная история
6.67
рейтинг книги
Солдат Империи

Неправильный лекарь. Том 1

Измайлов Сергей
1. Неправильный лекарь
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Неправильный лекарь. Том 1