Блокирование файлов
В этом разделе мы рассмотрим методы синхронизации работы программ, основанные на блокировании файлов.
Принцип блокирования файлов достаточно прост. Например, в MS-DOS, если запущена программа SHARE.EXE, программа, открывая файл, может указать, что этот файл будет использоваться ей монопольно. При попытке открыть этот файл еще раз другая программа получит от соответствующей функции MS-DOS код ошибки.
Для открывания файлов из программы, составленной на языке программирования C (или C++), удобно использовать функцию open():
int open(const char *path, int access [, unsigned mode]);
Для использования этой функции ваша программа должна содержать следующие две строки:
#include <fcntl.h> #include <sys\stat.h>
Функция возвращает индекс (handle) открытого файла или -1 в случае ошибки.
Параметр path указывает путь к открываемому файлу.
Параметр access определяет режим доступа к открываемому файлу. Вы можете использовать символические константы (их можно объединять при помощи логической операции ИЛИ):
Константа | Значение |
O_RDONLY | Открыть файл только для чтения |
O_WRONLY | Открыть файл только для записи |
O_RDWR | Открыть файл для чтения и записи |
O_APPEND | Добавлять записываемые данные в конец файла |
O_CREAT | Создать файл и открыть его. Если файл уже существует, ничего не происходит. Если файл не существует, он создается и открывается |
O_EXCL | Этот режим используется только вместе с режимом O_CREAT. Если файл уже существует, возвращается признак ошибки |
O_TRUNC | Открыть файл и установить для него нулевую длину |
O_BINARY | Файл открывается в двоичном режиме |
O_TEXT | Файл открывается в текстовом режиме. Для него выполняется преобразование байтов CR-LF в '\n' |
O_DENYNONE | К файлу разрешен множественный доступ со стороны нескольких программ, т. е. этот файл может быть открыт несколько раз |
O_DENYALL | Этот файл может быть открыт только один раз. Если другая программа попытается открыть файл для чтения или для записи, она получит признак ошибки |
O_DENYWRITE | Другая программа не может открыть этот файл еще раз для записи, но она может открыть его для чтения |
O_DENYREAD | Другая программа не может открыть этот файл еще раз для чтения, но она может открыть его для записи |
Необязательный параметр mode указывается только для вновь создаваемых файлов (в режиме O_CREAT). Он может принимать следующие значения:
Константа | Значение |
S_IWRITE | Разрешена запись в файл |
S_IREAD | Разрешено чтение файла |
Существует еще одна функция для открытия файлов, аналогичная функции open(), - функция sopen():
int sopen(path, access, shflag, mode);
Для использования этой функции в программу необходимо включить следующие строки:
#include <fcntl.h> #include <sys\stat.h> #include <share.h> #include <IO.H>
Параметры этой функции аналогичны параметрам функции open(). Дополнительный параметр shflag может принимать следующие значения:
Константа | Значение |
SH_COMPAT | Режим совместимости. Другие программы могут открывать файл, открытый в режиме совместимости, однако они также должны открывать его именно в режиме совместимости |
SH_DENYNONE | Другим программам разрешается открывать этот файл для записи и чтения, но не в режиме совместимости |
SH_DENYRD | Другие программы могут открывать этот файл, но только на запись |
SH_DENYRW | Другие программы могут открывать этот файл, но только на чтение |
Сетевая оболочка Novell NetWare предоставляет более удобные средства для блокирования файлов. Эти средства позволяют блокировать сразу несколько файлов, что может быть необходимо для обновления содержимого сложной базы данных.
Для того чтобы заблокировать один или несколько файлов средствами сетевой оболочки, вначале надо образовать группу, состоящую из блокируемых файлов. Для добавления файлов в группу служит функция LogFile(). Удалить файл из группы можно при помощи функции ClearFile().
После того как группа файлов создана, все эти файлы можно одновременно заблокировать при помощи функции LockFileSet(). Файлы можно блокировать и во время добавления их в группу.
Функция LogFile() имеет следующий прототип:
int LogFile(char *FileName, BYTE LockDirective,WORD Timeout);
Параметр FileName задает путь к файлу, который необходимо добавить в группу.
Параметр LockDirective определяет, надо ли блокировать файл сразу после его добавления в группу:
0x00 | Файл добавляется в группу, но не блокируется |
0x01 | Добавляемый файл блокируется для использования заблокировавшей его программой в монопольном режиме |
0x03 | Добавляемый файл блокируется для совместного использования |
Функция возвращает ноль при успешном завершении или код ошибки:
Код ошибки | Значение |
0x96 | Мало памяти на файл-сервере |
0xFE | Истек период ожидания, заданный параметром Timeout, но файл так и не удалось заблокировать |
0xFF | Сбой при блокировании файла |
int ClearFile(char *FileName);
Единственный параметр функции указывает путь к файлу, удаляемому из общего списка файлов, предназначенных для блокирования. Функция возвращает нулевое значение или значение 0xFF, если файла с указанным путем нет в списке.
Функция ClearFileSet() позволяет разблокировать все файлы группы и удалить группу:
void ClearFileSet(void);
Прототип функции LockFileSet(), используемой для блокирования группы файлов:
int LockFileSet(WORD Timeout);
Параметр Timeout используется так же, как и при вызове функции LogFile().
Функция возвращает 0 при успешном завершении или код ошибки:
Код ошибки | Значение |
0xFE | Истек период ожидания, заданный параметром Timeout, но файл так и не удалось заблокировать |
0xFF | Сбой при блокировании файла |
Для разблокирования отдельных файлов используйте функцию ReleaseFile():
int ReleaseFile(char *FileName);
Параметр FileName указывает путь к разблокируемому файлу. Функция возвращает нулевое значение или значение 0xFF, если файла с указанным путем нет в списке.
Если вам надо разблокировать сразу все файлы, добавленные в группу, используйте функцию ReleaseFileSet():
void ReleaseFileSet(void);
Для добавления файлов в группу вместо функции LogFile() можно использовать функцию EBh прерывания INT21h:
На входе: | AH | = | EBh; |
AL | = | Параметр LockDirective; | |
BP | = | Параметр Timeout.; | |
DS:DX | = | Адрес буфера, в котором находится путь к добавляе-мому файлу в формате текстовой строки, закрытой двоичным нулем. | |
На выходе: | AL | Код ошибки или 0, если операция завершилась без ошибок. |
На входе: | AH | = | EDh; |
DS:DX | = | Адрес буфера, в котором находится путь к файлу в формате текстовой строки, закрытой двоичным нулем. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
На входе: | AH | = | CFh; |
DS:DX | = | Адрес буфера, в котором находится путь к файлу в формате текстовой строки, закрытой двоичным нулем. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
На входе: | AH | = | CBh; |
AL | = | Регистр должен содержать нулевое значение; | |
BP | = | Параметр Timeout. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
На входе: | AH | = | ECh; |
DS:DX | = | Адрес буфера, в котором находится путь к файлу в формате текстовой строки, закрытой двоичным нулем. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
На входе: | AH | = | CDh. |
На выходе: | Регистры не используются. |