Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Локальные сети персональных компьютеров. Работа с сервером Novell NetWare

© Александр Фролов, Григорий Фролов
Том 9, М.: Диалог-МИФИ, 1993, 168 стр.

[Назад] [Содеожание] [Дальше]

5.1. Блокирование файлов

В этом разделе мы рассмотрим методы синхронизации работы программ, основанные на блокировании файлов.

Принцип блокирования файлов достаточно прост. Например, в 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 Добавляемый файл блокируется для совместного использования

Параметр Timeout определяет период времени (в 18-х долях секунды), в течение которого файл-сервер будет ожидать, если файл нельзя заблокировать немедленно. Если для этого параметра задать нулевое значение, ожидание выполняться не будет.

Функция возвращает ноль при успешном завершении или код ошибки:

Код ошибки Значение
0x96 Мало памяти на файл-сервере
0xFE Истек период ожидания, заданный параметром Timeout, но файл так и не удалось заблокировать
0xFF Сбой при блокировании файла

Для удаления файла из группы можно использовать функцию ClearFile():

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 прерывания INT 21h:

На входе: AH = EBh;
AL = Параметр LockDirective;
BP = Параметр Timeout.;
DS:DX = Адрес буфера, в котором находится путь к добавляе-мому файлу в формате текстовой строки, закрытой двоичным нулем.
На выходе: AL Код ошибки или 0, если операция завершилась без ошибок.

Для удаления файла из списка вместо функции ClearFile() можно использовать функцию EDh прерывания INT 21h:

На входе: AH = EDh;
DS:DX = Адрес буфера, в котором находится путь к файлу в формате текстовой строки, закрытой двоичным нулем.
На выходе: AL = Код ошибки или 0, если операция завершилась без ошибок.

Для удаления группы файлов и разблокирования всех файлов вместо функции ClearFileSet() можно использовать функцию CFh прерывания INT 21h:

На входе: AH = CFh;
DS:DX = Адрес буфера, в котором находится путь к файлу в формате текстовой строки, закрытой двоичным нулем.
На выходе: AL = Код ошибки или 0, если операция завершилась без ошибок.

Для блокирования группы файлов вместо функции LockFileSet() можно использовать функцию CBh прерывания INT 21h:

На входе: AH = CBh;
AL = Регистр должен содержать нулевое значение;
BP = Параметр Timeout.
На выходе: AL = Код ошибки или 0, если операция завершилась без ошибок.

Для разблокирования файла вместо функции ReleaseFile() можно использовать функцию ECh прерывания INT 21h:

На входе: AH = ECh;
DS:DX = Адрес буфера, в котором находится путь к файлу в формате текстовой строки, закрытой двоичным нулем.
На выходе: AL = Код ошибки или 0, если операция завершилась без ошибок.

Для разблокирования группы файлов вместо функции ReleaseFileSet() можно использовать функцию CDh прерывания INT 21h:

На входе: AH = CDh.
На выходе: Регистры не используются.

5.1.1. Программа FLOCK

Приведем пример программы FLOCK (листинг 21), выполняющей блокирование файлов средствами сетевой оболочки.

Вначале программа в цикле запрашивает пути к блокируемым файлам до тех пор, пока оператор вместо имени файла не введет символ "-". Каждый введенный файл добавляется в группу при помощи функции LogFile().

Затем вся группа блокируется функцией LockFileSet().

Далее программа ожидает нажатия на любую клавишу. Попробуйте просмотреть содержимое заблокированных файлов с другой рабочей станции - это у вас не получится.

После того как вы нажмете на любую клавишу, программа разблокирует группу файлов при помощи функции ReleaseFileSet() и удалит саму группу, вызывая функцию ClearFileSet(). Файлы, разумеется, не удаляются с диска, удаляется только группа путей к файлам, которая использовалась для блокирования.

// ===================================================
// Листинг 21. Блокирование файлов
// Файл flock\flock.cpp
//
// (C) A. Frolov, 1993
// ===================================================

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>

#define BYTE unsigned char
#define WORD unsigned int

extern "C" int GetNetWareShellVersion(char *,char *, char *);
extern "C" int LogFile(char *, BYTE, WORD);
extern "C" int LockFileSet(WORD);
extern "C" void ReleaseFileSet(void);
extern "C" void ClearFileSet(void);

void main(void) {

        char MajorVersion=0;
        char MinorVersion=0;
        char Revision=0;

        char FilePath[255];

        int ccode;

        printf("\n*FLOCK* (C) Frolov A., 1993\n");

// Проверяем наличие сетевой оболочки

        asm push si
        GetNetWareShellVersion(&MajorVersion,
                        &MinorVersion, &Revision);
        asm pop si

        if(MajorVersion == 0) {
                printf("\nОболочка NetWare не загружена\n");
                return;
        }

// Создаем набор файлов, которые будут заблокированы

        for(;;) {
                printf("\nВведите путь к файлу или '-':");
                gets(FilePath);

                strupr(FilePath);
                if(FilePath[0] == '-') break;

// Добавляем файл в набор

                ccode = LogFile(FilePath, 0, 0);

                if(!ccode)
                        printf("Файл %s добавлен к списку\n", FilePath);
                else
                        printf("Ошибка при добавлении %02.2X\n", ccode);
        }

// Блокируем набор файлов

        ccode = LockFileSet(0);

        if(!ccode)
                printf("Файлы заблокированы\n");
        else
                printf("Ошибка при блокировании "
                          "файлов %02.2X\n", ccode);

        printf("Для разблокирования файлов нажмите любую клавишу\n");
        getch();

// Разблокируем набор файлов

        ReleaseFileSet();

// Удаляем набор файлов

        ClearFileSet();
}


[Назад] [Содеожание] [Дальше]