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

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

F_GETLEASE

Возвращается тип аренды, существующей в настоящий момент для файла (

F_RDLCK
,
F_WRLCK
или
F_UNLCK
).

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

SIGIO
, но процесс может выбрать, какой сигнал передавать этому файлу, с помощью вызова
fcntl
, в котором второй параметр установлен в
F_SETSIG
, а последний — в сигнал, который должен использоваться вместо
SIGIO
.

Использование

F_SETSIG
дает один значительный
эффект. По умолчанию
siginfo_t
не передается обработчику при доставке
SIGIO
. Если используется
F_SETSIG
, даже когда сигналом, передаваемым в ядро, является
SIGIO
, a
SA_SIGINFO
был установлен при регистрации обработчика сигнала, файловый дескриптор, аренда которого инициировала событие, передается в обработчик сигналов одновременно с элементом
siginfo_t
по имени
si_fd
. Это позволяет применять отдельный сигнал к аренде множества файлов, в то время как
si_fd
сообщает сигналу, какому файлу необходимо уделить внимание [96] .

96

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

Единственные два системных вызова, которые могут инициировать передачу сигнала для арендуемого файла — это

open
и
truncate
. Когда они вызываются процессом для арендуемого файла, они блокируются [97] , и процессу-владельцу передается сигнал,
open
или
truncate
завершаются после удаления аренды с файла (или его закрытия процессом-владельцем, что вызывает удаление аренды). Если процесс, удерживающий аренду, не отменяет снятие в течение времени, указанного в файле
/proc/sys/fs/lease-break-time
, ядро прерывает аренду и позволяет завершиться запускающему системному вызову.

97

До тех пор пока

O_NONBLOCK
не будет определен как флаг
open
; в этом случае возвращается
EWOULDBLOCK
.

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

 1: /* leases.с */

 2:

 3: #define GNU_SOURCE

 4:

 5: #include <fcntl.h>

 6: #include <signal.h>

 7: #include <stdio.h>

 8: #include <string.h>

 9: #include <unistd.h>

10:

11: const char ** fileNames;

12: int numFiles;

13:

14: void handler (int sig, siginfo_t * siginfo, void * context) {

15: /* Когда аренда
истекает, вывести сообщение и закрыть файл.

16: Предполагается, что первый открываемый файл получит файловый

17: дескриптор 3, следующий - 4 и так далее. */

18:

19: write(1, "освобождение", 10);

20: write(1, fileNames[siginfo->si_fd - 3],

21: strlen(fileNames[siginfo->si_fd - 3]));

22: write(1, "\n", 1);

23: fcntl(siginfo->si_fd, F_SETLEASE, F_UNLCK);

24: close(siginfo->si_fd);

25: numFiles--;

26: }

27:

28: int main(int argc, const char ** argv) {

29: int fd;

30: const char ** file;

31: struct sigaction act;

32:

33: if (argc < 2) {

34: fprintf(stderr, "использование: %s <filename>+\n", argv[0]);

35: return 1;

36: }

37:

38: /* Зарегистрировать обработчик сигналов. Указав SA_SIGINFO, предоставить

39: обработчику возможность узнать, какой файловый дескриптор имеет

40: истекшую аренду. */

41: act.sa_sigaction = handler;

42: act.sa_flags = SA_SIGINFO;

43: sigemptyset(&act.sa_mask);

44: sigaction(SIGRTMIN, &act, NULL);

45:

46: /* Сохранить список имен файлов в глобальной переменной, чтобы

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

48: fileNames = argv + 1;

49: numFiles = argc - 1;

50:

51: /* Открыть файлы, установить используемые сигнал

52: и создать аренду */

53: for (file = fileNames; *file; file++) {

54: if ((fd = open(* file, O_RDONLY)) < 0) {

55: perror("open");

56: return 1;

57: }

58:

59: /* Для правильного заполнения необходимо использовать F_SETSIG

60: для структуры siginfo */

61: if (fcntl(fd, F_SETSIG, SIGRTMIN) < 0) {

62: perror("F_SETSIG");

63: return 1;

64: }

65:

66: if (fcntl(fd, F_SETLEASE, F_WRLCK) < 0) {

67: perror("F_SETLEASE");

68: return 1;

69: }

70: }

71:

72: /* Пока файлы остаются открытыми, ожидать поступления сигналов. */

73: while (numFiles)

74: pause;

75:

76: return 0;

77: }

13.4. Альтернативы

read
и
write

Поделиться с друзьями: