Главная страница Взаимодействие нетривиальных процессов и если они не выполнялись параллельно, мы не имеем возможности увидеть ошибку. Увеличить шансы обнаружения ошибки можно, изменив функцию та i п таким образом, чтобы последовательный номер увеличивался 10 ООО раз, и запустив 20 экземпляров программы одновременно. Если начальное значение последовательного номера в файле было 1, мы можем ожидать, что после завершения работы всех этих процессов мы увидим в файле число 200 001. Пример: упрощение с помощью макросов в листинге 9.3 установка и снятие блокировки занимали шесть строк кода. Мы должны вьщелить место под структуру, инициализировать ее и затем вызвать fcntl. Программы можно упростить, если определить следующие семь макросов, которые взяты из раздела 12.3 [21]: fdefine read lock(fd, offset, whence, len) \ lock reg(fd. F SETLK, FJDLCK, offset, whence, len) fdefine readw lock(fd, offset, whence, len) \ lock reg(fd. F SETLKW. F ROLCK. offset, whence, len) fdefine write lock(fd. offset, whence, len) \ lock reg(fd, F SETLK, F WRLCK. offset, whence, len) fdefine writew lock(fd. offset, whence, len) \ lock reg(fd, F SETLKW, F WRLCK, offset, whence, len) fdefine unJock(fd. offset, whence, len) \ lock reg(fd, F SETLK, F UNLCK, offset, whence, len) fdefine is readJockable(fd, offset, whence, len) \ lock test(fd, F RDLCK, offset, whence, len) fdefine is write lockable(fd, offset, whence, len) \ lock test(fd, F WRLCK, offset, whence, len) Эти макросы используют наши функции lock reg и lock test, текст которых приведен в листингах 9.4 и 9.5. С ними нам уже не нужно заботиться об инициализации структур и вызове функций. Первые три аргумента специально сделаны совпадающими с первыми тремя аргументами функции 1 seek. Мы также определяем две функции-обертки, Lock reg и Lock test, завершающие свое выполнение с возвратом ошибки fcntl, и семь макросов с именами, начинающимися с заглавной буквы, чтобы эти функции вызывать. С помощью новых макросов мы можем записать функции ту 1 оск и my unl оск из листинга 9.3 как fdefine rnyjock(fd) (WritewJock(fd, О, SEEKJET, 0)) fdefine my unlock(fd) (UnJock(fd, 0, SEEKJET, 0)) Листинг 9.4. Вызов fcntl для получения и снятия блокировки lib/lock reg.c 1 finclude unpipc.h 2 int 3 lock reg(int fd, int cmd, int type, off t offset, int whence, off t len) 5 struct flock lock: 6 1 ock. 1 Jype - type: /* F RDLCK. F WRLCK, FJNLCK */ 7 lock,l start - offset: /* сдвиг no отношению к l whence */ 8 lock.l whence - whence: /* SEEK SET, SEEK CUR, SEEK END */ 9 lock.ljen - len; /* количество байтов (О - до конца файла) */ 10 returnC fcntl (fd, cmd. &1оск) ): /* -1 в случае ошибки */ И } Листинг 9.5. Вызов fcntl для проверки состояния блокировки lib/lock test.c 1 linclude unpipc.h 2 pid t 3 lock test(int fd. int type, off t offset, int whence, off t len) 5 struct flock lock: 6 lock.l type = type: /* F RDLCK or F WRLCK */ 7 lock.l start = offset: /* сдвиг no отношению к l whence */ 8 lock.l whence = whence: /* SEEKJET, SEEK CUR, SEEKJND */ 9 lock.ljen - len: /* количество байтов, О - до конца файла */ 10 if (fcntKfd, F GETLK, &1оск) == -1) И return(-l); /* непредвиденная ошибка */ 12 if (lock,l type - F UNLCK) 13 return(O): /* false, область не заблокирована другим процессом */ 14 return(lock.l pid): /* true, возвращается положительный PID процесса, заблокировавшего ресурс */ 15 } 9.4. Рекомендательная блокировка Блокировка записей по стандарту Posix называется рекомендательной. Ядро хранит информацию обо всех заблокированных различными процессами файлах, но оно не предотвращает запись в заблокированный на чтение процесс. Ядро также не предотвращает чтение из файла, заблокированного на запись. Процесс может игнорировать рекомендательную блокировку (advisory lock) и действовать по своему усмотрению (если у него имеются соответствующие разрешения на чтение и запись). Рекомендательные блокировки отлично подходят для сотрудничающих процессов (cooperating processes). Примером сотрудничающих процессов являются сетевые демоны: все они находятся под контролем системного администратора. Пока в файл, содержащий порядковый номер, запрещена запись, никакой процесс не сможет его изменить. Пример: несотрудничающие процессы Мы можем проиллюстрировать рекомендательный характер блокировок, запустив два экземпляра нашей программы, один из которых (lockfcntl) использует функции из листинга 9.3 и блокирует файл перед увеличением последовательного номера, а другой (1 оскпопе) использует функции из листинга 9.1 и не устанавливает никаких блокировок:
Программа 1 ockfcntl запускается первой, но в тот момент, когда она выполняет три действия для увеличения порядкового номера с И до 12 (в этот момент файл заблокирован), ядро переключается на второй процесс и запускает программу locknone. Этот процесс считывает значение И из файла с порядковым номером и использует его. Рекомендательная блокировка, установленная для этого файла программой 1 ockfcntl, никак не влияет на работу программы 1 ocknone. 9.5. Обязательная блокировка Некоторые системы предоставляют возможность установки блокировки другого типа - обязательной (mandatory locking). В этом случае ядро проверяет все вызовы read и write, блокируя их при необходимости. Если для дескриптора уста-
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |