Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
А4_Методичка.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
4 Мб
Скачать
☆

4.4. Програмування роботи з об’єктами, діагностика обчислювальних мереж.

4.4.1 Робота з об’єктами. [20]

Об'єкти, коди об'єктів і права доступу. Файл-сервер Novell NetWare містить БД об'єктів, в якій є відомості про ресурси, доступні в мережі (файл-сервери, сервери друку і т. д.), про користувачів і групи користувачів і т. д. Ця БД називається Bindery. Фізично вона знаходиться в двох прихованих файлах з іменами net$bind.sys і net$bval.sys, розташованих в каталозі SYS: SYSTEM.

Кожен об'єкт, що зберігається в базі даних, має своє ім'я, унікальний для даного файл-сервера ідентифікатор, тип, байт доступу. Крім того, об'єкт може бути статичним або динамічним.

Наприклад, кожен користувач, доданий супервізором КМ / адміністратором, стає об'єктом, у якого є ім'я та ідентифікатор. Тип такого об'єкта відповідає значенню 1, і це статичний об'єкт. Статичний об'єкт зберігається в базі до тих пір, поки він не буде видалений явним чином.

Якщо в КМ є кілька файл-серверів, то для кожного сервера в базі Bindery є об'єкти, які відповідають усім серверам, активним у КМ. Це тимчасові об'єкти, які видаляються автоматично, коли відповідний файл-сервер припиняє свою роботу. Можна користатися цією обставиною для отримання списку активних серверів, що є в КМ.

ПП можуть не тільки зчитувати вміст бази об'єктів, але і додавати свої власні записи, а також редагувати існуючі. Розглянемо способи добування інформації з бази Bindery.

БД Bindery зберігає об'єкти, які мають такі атрибути, як ідентифікатор, ім'я, тип, флаг(статичний / динамічний об'єкт), байт доступу.

Ідентифікатор об'єкта - число розміром 4 байта, яке є унікальним для даного файл-сервера. Ніякі два об'єкти, відомості про які зберігаються в одній БД на одному сервері, не можуть мати однакові ідентифікатори.

Назва об'єкту являє собою текстовий рядок розміром не більше 47 байт. В операціях пошуку об'єктів в БД по імені в полі імені допускається вказувати символи "*" та "?", Які інтерпретуються так як в MS-DOS.

В бібліотеці NetWare C Interface функції, які дозволяють переглядати список всіх об'єктів БД, шукати об'єкти певного типу або по імені з використанням шаблону і символів "*" та "?". За ідентифікатором об'єкта можна легко отримати його ім'я і навпаки, по імені можна дізнатися ідентифікатор об'єкта. Тип об'єкта визначає мережевий ресурс і можуть приймати значення, які наведені в табл. 4.2.

Таблиця.4.2

Значення

Опис

0

Некласифікований( невідомий) об’єкт

1

Користувач

2

Група користувачів

3

Очікування друку

4

Файл-сервер

5

Сервер завдань

6

Шлюз

7

Сервер друку

8

Черга для архівування

9

Сервер для архівування

A

Черга завдань 

B

Адміністратор

24

Сервер увіддаленого моста

Флаг об'єкту характеризує час життя об'єкту. Якщо цей показник дорівнює нулю, об'єкт статичний і для його знищення необхідно викликати спеціальну функцію. Якщо показник дорівнює одиниці, то це динамічний об'єкт, який видаляється автоматично, як тільки зникає відповідний мережевий ресурс.

Наприклад, якщо в КМ є кілька файл-серверів, в базі кожного сервера є об'єкти, які описують всі активні сервери Км. Як тільки один з серверів припиняє свою роботу, з усіх баз даних, розташованих на інших файл-серверах, видаляються об'єкти, що описують завершення роботи файл-серверу.

Байт доступу використовується для визначення прав, необхідних для пошуку, читання, створення, редагування / видалення. Дві тетради байта відповідають за доступ на читання і доступ на запис. Молодші чотири біта байта доступу відповідають за читання, старші - за запис.

Для тетрад визначено значення від 0 до 4 - рівні доступу. Для того, щоб користувач або інший об'єкт отримали доступ, тетради його власного байта доступу повинні мати значення, рівні або більші значень в байті доступу об'єкта, до якого здійснюється доступ.

Наведемо список можливих значень для рівнів доступу: 0 - (Anyone) об’єкт не підключений до файл-серверу; 1 - (Logged) об’єкт підключений до файл-серверу; 2 - (Object) об’єкт підключений до файл-серверу с з іменем і паролем; 3 - (Supervisor) об’єкт має права супервізора; 4 - (NetWare) об’єкт має права ОС Novell NetWare.

Для визначення власного рівня доступу та ідентифікатора користувача програма може скористатися функцією GetBinderyAccessLevel ():

int GetBinderyAccessLevel(BYTE *SecurityAccessLevel, long *ObjectID);

Перший параметр цієї функції вказує на слово, в яке буде записаний рівень доступу, другий - на подвійне слово, в яке буде записаний ідентифікатор користувача.

Замість функції GetBinderyAccessLevel () можна використовувати функцію E3h переривання INT 21h:

На вході: AH = E3h; DS: SI = Адреса буфера запиту; ES: DI = Адреса буфера відповіді.

На виході: AL = Код помилки або 0, якщо операція завершилася без помилок.

Буфер запиту має наступний формат:

struct REQUEST {

WORD PacketLength; / / розмір пакета запиту

BYTE Function; / / повинен дорівнювати 70

};

Буфер відповіді має наступний формат:

struct REPLAY {

WORD PacketLength; / / розмір пакета

BYTE SecurityAccessLevel; / / рівень доступу

long ObjectID; / / ідентифікатор об'єкта

};

За ідентифікатором об'єкта ви можете отримати його ім'я і тип за допомогою функції GetBinderyObjectName ():

int GetBinderyObjectName (long ObjectID,

char * ObjectName, WORD * ObjectType);

Для об'єкта, ідентифікатор якого заданий першим параметром, функція повертає ім'я об'єкта і його тип, записуючи їх в області ОП, зазначені за допомогою другого і третього параметрів.

Функція повертає 0 при успішному завершенні або код помилки: 0x96 - мало пам’яті на сервері; 0xFC - в базі немає об’екту з вказаним ідентифікатором; 0xFE - БД Bindery заблокована; 0xFF - збій БД Bindery.

Замість функції GetBinderyObjectName () ви також можете використовувати функцію E3h переривання INT 21h. При цьому необхідно використовувати формати буфера запиту і буфера відповіді, наведені нижче.

Буфер запиту:

struct REQUEST {

WORD PacketLength; / / розмір пакета запиту

BYTE Function; / / повинен дорівнювати 54

long ObjectID; / / ідентифікатор об'єкта

};

Буфер відповіді:

struct REPLAY {

WORD PacketLength; / / розмір пакета

Long ObjectID; / / ідентифікатор об'єкта

WORD ObjectType; / / тип об'єкта

BYTE ObjectName [48]; / / ім'я об'єкта

};

Для отримання ідентифікатора об'єкта по його імені і типу ви можете скористатися функцією GetBinderyObjectID ():

int GetBinderyObjectID (char * ObjectName, WORD ObjectType,

long * ObjectID);

Ім'я та тип об'єкта задаються першим і другим параметрами, ідентифікатор записується за адресою, заданою третім параметром.

Функція повертає 0 при успішному завершенні або код помилки: 0x96 - мало пам'яті на сервері; 0xEF - назва об'єкту вказано неправильно; 0xF0 - не допускаються символи шаблону "*", "?"; 0xFC - у базі немає об'єкта з вказаним ідентифікатором; 0xFE - БД Bindery заблокована; 0xFF - Збій БД Bindery.

Замість функції GetBinderyObjectID() можна використовувати функцію E3h переривання INT 21h. Наведемо формати буфера запиту і буфера відповіді.

Буфер запиту:

struct REQUEST {

WORD PacketLength; // розмір пакета запиту

BYTE Function; // повинен дорівнювати 53

long ObjectType; // тип об'єкта

BYTE ObjectNameLength; // довжина імені об'єкта

BYTE ObjectName [ObjectNameLength]; / / ім'я об'єкта

};

Буфер відповіді:

struct REPLAY {

WORD PacketLength; / / розмір пакета

long ObjectID; / / ідентифікатор об'єкта

WORD ObjectType; / / тип об'єкта

BYTE ObjectName [48]; / / ім'я об'єкта };

Програма для визначення властивостей заданого об’єкта.

Розглянемо завдання сканування БД Bindery з метою отримання списку наявних у ній об'єктів. Наприклад, якщо знадобиться список активних серверів в КМ, список користувачів або список робочих груп.

Для отримання списку об'єктів, відомості про які зберігаються в БД Bindery, призначена функція ScanBinderyObject ():

int ScanBinderyObject (char * SearchObjectName,

WORD SearchObjectType, long * ObjectID, char * ObjectName,

WORD * ObjectType, char * ObjectHasProperties,

char * ObjectFlag, char * ObjectSecurity);

Ця функція повинна використовуватися в циклі. При першому виклику в змінну, на яку вказує параметр ObjectID, необхідно записати значення -1. Надалі в цю змінну буде записуватися ідентифікатор знайденого об'єкта.

Для пошуку слід вказати ім'я об'єкта (параметр SearchObjectName) і тип об'єкта (параметр SearchObjectType). Як ім'я об'єкта можна використовувати шаблон з символами "*" та "?". Тип об'єкта може бути заданий конкретно, або можна вказати значення -1. В останньому випадку функція буде шукати об'єкти всіх типів. Для того щоб знайти всі об'єкти всіх типів, в якості імені треба вказати рядок "*", в якості типу задати значення -1.

Для знайдених об'єктів у відповідні змінні, зазначені параметрами функції, будуть записані ім'я об'єкта (параметр ObjectName), тип об'єкта (параметр ObjectType), прапор (параметр ObjectFlag), байт доступу (параметр ObjectSecurity). Крім того, в змінну, на яку вказує параметр ObjectHasProperties, записується значення 0xFF, якщо об'єкт має додаткову пов'язану з ним інформацію (Properties), яку можна витягти спеціально призначеними для цього функціями.

Функція повертає 0 при успішному завершенні або код помилки: 0x96 - мало пам'яті на сервері; 0xEF - назву об'єкту вказано неправильно; 0xFC - у БД немає об'єкта з вказаним ідентифікатором; 0xFE - БД Bindery заблокована; 0xFF - збій БД Bindery.

ПП повинна викликати функцію ScanBinderyObject () у циклі до тих пір, поки вона не поверне код помилки, відмінний від нуля.

Замість функції ScanBinderyObject () можна використовувати функцію E3h переривання INT 21h: На вході: AH = E3h; DS: SI = Адреса буфера запиту; ES: DI = Адреса буфера відповіді.

На виході: AL = Код помилки або 0, якщо операція завершилася без помилок.

Буфер запиту має наступний формат:

struct REQUEST {

WORD PacketLength; // розмір пакета запиту

BYTE Function; // повинен бути дорівнює 55

BYTE ObjectID; // ідентифікатор об'єкта

WORD SearchObjectType; // тип об'єкта

BYTE NameLength; // довжина імені зразка для

/ / Пошуку об'єкта

BYTE SearchObjectName [NameLength]; // ім'я зразка для

/ / Пошуку об'єкта

};

Буфер відповіді має наступний формат:

struct REPLAY {

WORD PacketLength; / / розмір пакета

long ObjectID; / / ідентифікатор об'єкта

WORD ObjectType; / / тип об'єкта

BYTE ObjectName [48]; / / ім'я об'єкта

BYTE ObjectFlag; / / прапор об'єкта

BYTE SecurityAccessLevel; / / рівень доступу

BYTE ObjectHasProperties; / / є записи };

У БД об'єктів Bindery з кожним об'єктом може бути пов'язано кілька додаткових записів, що містять дані (property). Кожен такий запис має своє ім'я, позначку і байт доступу. Якщо об'єкт має записи, то можна отримати список їхніх імен та інших атрибутів за допомогою функції ScanProperty ():

int ScanProperty (char * ObjectName, WORD ObjectType,

char * SearchPropertyName, long * SequenceNumber,

char * PropertyName, char * PropertyFlag,

char char * PropertySecurity,

char * PropertyHasValue, char * MoreProperties);

Функція викликається в циклі. При першому виклику змінна, на яку вказує параметр SequenceNumber, повинна містити значення -1. При наступних викликах значення цієї змінної змінюється автоматично.

Для зчитування полів функції необхідно вказати ім'я скануючого об'єкта (параметр ObjectName), тип об'єкта (ObjectType), а також ім'я запису або шаблон імені запису (SearchPropertyName). У шаблоні можна використовувати символи "*" та "?".

Для знайдених записів у відповідні змінні, зазначені параметрами функції, будуть записані ім'я запису (PropertyName), прапор запису (PropertyFlag), байт доступу (параметр PropertySecurity), ознака того, що запис має значення (PropertyHasValue), ознака того, що в об'єкті є ще й інші записи (MoreProperties).

Функція повертає 0 при успішному завершенні або такі коди помилки: 0x96 - мало пам'яті на сервері; 0xF1 - неправильний код доступу; 0xFB - зазначена запис не знайдено; 0xFC - у БД немає об'єкта з вказаним ідентифікатором; 0xFE - БД Bindery заблокована; 0xFF - збій БД Bindery.

У Novell NetWare для кожного типу об'єкту існує певний набір записів, які можуть бути пов'язані з цим об'єктом. Наприклад, з об'єктом типу 1 (звичайний користувач) пов'язані такі записи, як PASSWORD (пароль) і SECURITY_EQUALS (еквівалентність прав доступу). Значення записів можна зчитати за допомогою функції ReadPropertyValue () з бібліотеки NetWare C Interface.

Деякі імена полів, визначених у NetWare наведені в табл.4.3. Повний список полів і докладний їх опис можна знайти в документації по бібліотеці NetWare C Interface.

Таблиця.4.3

Ім'я запису

Тип об'єкта

Доступ, запис / зчитування

BLOCKS_READ

Файл-сервер

3 / 1

BLOCKS_WRITTEN

Файл-сервер

3 / 1

CONNECT_TIME

Файл-сервер

3 / 1

GROUP_MEMBERS

Група користувачів

3 / 1

GROUPS_I'M_IN

Користувач

3 / 1

IDENTIFICATION

Користувач

3 / 1

NET_ADDRESS

Файл-сервер

4 / 0

OLD_PASSWORDS

Користувач

3 / 3

OPERATORS

Файл-сервер

3 / 3

PASSWORDS

Користувач

4 / 4

SECURITY_EQUALS

Користувач

3 / 2

Програма блокування файлу на системному пристрою представлена у ПП. 25 на CD.

ЛКМ – різновид багатокористувацької системи, в якій реалізований множинний доступ до файлів, що зберігаються на файл-сервері. У однокористувальницькому однозадачному середовищі, такому, як MS-DOS, в кожен момент часу до будь-якого файлу може звертатися тільки одна ПП. Якщо користувач працює в середовищі Microsoft Windows, що є однокористувальницьким багатозадачним середовищем, існує можливість одночасного звернення до одного і того ж файлу з декількох працюючих одночасно додатків.

У КМ Novell NetWare також є можливість одночасного доступу до файлів, що зберігаються в мережевих каталогах, з боку різних РС. Причому на цих РС може працювати багатозадачна ОС, наприклад W' Х, що ще більше ускладнює ситуацію.

До чого може призвести неправильна обробка множинного доступу до файлів?

Нехай, наприклад, на рахунку фірми лежить 2 млн. грн.., виділені на покупку деякого товару. Двом торговим агентам дано доручення купити товар на суму 1,5 млн. грн. Перший агент знайшов товар і перевів гроші з рахунку своєї фірми на рахунок фірми-власника товару. Для того щоб переказати гроші, торговий агент скористався програмою, яка читає з файлу БД вміст поля, що відбиває суму, виділену на купівлю товару. Потім програма віднімає з неї вартість товару і записує в файл нове значення.

Другий торговий агент теж не втрачав часу дарма і знайшов свій товар майже одночасно з першим. Він приступив до переказу грошей майже відразу після першого агента. Вийшло так, що перший агент встиг тільки читати старе значення відповідного поля, але не встиг записати нове (0,5 млн. грн.). Тому програма, запущена другим агентом, читала з поля БД значення 2 млн. грн., не дивлячись на те, що перший агент вже зробив свою покупку і грошей залишилося менше.

Тепер перший агент записує в поле нове значення, і через деякий час те ж саме робить другий агент. Отже, на суму в 2 млн. грн. успішно зроблено дві покупки за 1,5 млн. грн. і ще на рахунку фірми залишилося 0,5 млн. грн.! Хто ж буде покривати збитки розміром 1,5 млн. грн.? Очевидно, програміст, який склав таку програму!

Як вийти з такої скрутної ситуації? Очевидно, що, як тільки перший торговий агент приступив до переказу грошей, файл БД або, що краще, відповідний запис у БД повинен бути заблокований від спроб його читання / зміни. Тільки тоді, коли процес зміни запису завершено, можна дозволяти іншим програмам читати запис.

Ще один спосіб заснований на використанні глобальних змінних, розташованих на файл-сервері і доступних з усіх РС - так званих семафорів.

Сервіс синхронізації.

Константа

Значення

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

Інша програма не може відкрити цей файл ще раз для читання, але вона може відкрити його для запису

Блокування файлів

Розглянемо методи синхронізації роботи програм, заснованих на блокуванні файлів.

Принцип блокування файлів досить простий. Наприклад, в 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 визначає режим доступу до файлу, що відкривається. Можна використовувати символічні константи (їх можна об'єднувати за допомогою логічної операції АБО).

Необов'язковий параметр 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 визначає період часу (у тіках), протягом якого файл-сервер буде чекати, якщо файл не можна заблокувати негайно. Якщо для цього параметра задати нульове значення, очікування виконуватися не буде. Функція повертає нуль при успішному завершенні або код помилки: 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 = 0; BP = Параметр Timeout.

На виході: AL = Код помилки або 0, якщо операція завершилася без помилок.

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

На вході: AH = ECh; DS: DX = Адреса буфера, в якому знаходиться шлях до файлу у форматі текстового рядка, закритою двійковим нулем.

На виході: AL = Код помилки або 0, якщо операція завершилася без помилок.

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

На вході: AH = CDh.

На виході: Регістри не використовуються

Більше про блокування файлів, а саме: блокування фізичних записів, блокування логічних записів можна прочитати в [20].