Лекції з WinApi

Тема №8 Робота з файлами

8. Робота з файлами
 8.1. Файлові структури

Windows 95 підтримує роботу з файловими структурами FAT і CDFS. При цьому Windows 95 працює з розширеним варіантом FAT, що підтримує імена довжиною до 255 символів. CDFS - файлова структура призначена для компакт-дисків.

На додаток до цьому Windows NT підтримує роботу ще з двома файловими структурами NTFS і HPFS.

NTFS (New Technology File System) - структура призначена для організації даних на твердому диску. NTFS надає всі можливості FAT, значно розширюючи їх. Доступ до файлів у NTFS, як правило, більш швидкий ніж у FAT. NTFS файлова система, що самовідновлюється. Вона стійка до краху додатків, системи, операцій введення-висновку і розроблена таким чином, щоб відновлювати коректність даних без використання спеціальних сервісних програм перевірки дисків. NTFS підтримує розмежування доступу до файлів, імена файлів у довільному алфавіті. Докладно вивчається в розділі 9.5.

HPFS (High-Performance File System) - так само організує дані на твердому диску. У порівнянні з FAT вона підвищує продуктивність системи за рахунок використання кэширування. Підтримується Windows з метою сумісності. По можливості рекомендується заміняти HPFS на NTFS.

8. Робота з файлами

 8.2. Робота з томами і каталогами

Для з'ясування того, які логічні диски існують у системі, використовується функція

DWORD GetLogicalDrives( void )

Кожен установлений біт значення, що повертається, відповідає існуючому в системі логічному пристрою. Наприклад, якщо в системі існують диски A:, C: і D:, те значення, що повертається функцією, дорівнює 10(10).

Функція

DWORD GetLogicalDrivesStrings( DWORD cchBuffer, LPTSTR lpszBuffer)

заповнює lpszBuffer інформацією про кореневий каталог кожного логічного диска в системі. У приведеному вище прикладі буфер буде заповнений символами

A:\<null>C:\<null>D:\<null><null>

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

DWORD dw = GetLogicalDrivesStrings( 0, NULL ) ;

LPSTR lpDriveStrings = HeapAlloc( GetProcessHeap(), 0, dw*sizeof(TCHAR));

GetLogicalDrivesStrings( dw, lpDriveStrings );

Для визначення типу диска призначена функція

UINT GetDriveType( LPTSTR lpszRootPathName )

Як параметр їй передається символічне ім'я кореневого каталогу (напр. A:\), а значення, що повертається, може бути одне з наступних:

Ідентифікатор

Опис

0

Тип пристрою визначити не можна

1

Корнєвої каталог не існує

DRIVE_REMOVABLE

Гнучкий диск

DRIVE_FIXED

Твердий диск

DRIVE_REMOTE

Мережний диск

DRIVE_CDROM

Компакт диск

DRIVE_RAMDISK

RAM диск (емуліруємий в оперативній пам'яті)

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

Функція GetDiskFreeSpace повідомляє інформацію про розміри сектора і кластера і про наявність вільних кластерів.

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

Для роботи з каталогами і файлами, як з об'єктами, призначені наступні функції:

Функція

Виконувана дія

GetCurrentDirectory

Одержання поточного каталогу

SetCurrentDirectory

Зміна поточного каталогу

GetSystemtDirectory

Одержання системного каталогу

GetWindowstDirectory

Одержання основного каталогу системи

CreateDirectory

Створення каталогу

RemoveDirectory

Видалення каталогу

CopyFile

Копіювання файлу

MoveFile

MoveFileEx

 Чи переміщення перейменування файлу

DeleteFile

Видалення файлу

8. Робота з файлами.
 8.3. Синхронна робота з файлами.

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

У Win32 перед ухваленням рішення про використання операцій синхронної роботи з файлами настійно рекомендується розглянути питання про можливість використання файлів, відображуваних у пам'ять.

Для того, щоб чи створити відкрити файл використовується функція

HANDLE CreateFile(

LPCTSTR lpFileName, // pointer to name of the file

DWORD dwDesiredAccess, // access (read-write) mode

DWORD dwShareMode, // share mode

LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security descriptor

DWORD dwCreationDistribution, // how to create

DWORD dwFlagsAndAttributes, // file attributes

HANDLE hTemplateFile // handle to file with attributes to copy

);

Параметр lpFileName визначає ім'я файлу.

Параметр dwDesiredAccess задає тип доступу до файлу. Можна визначити прапори GENERIC_READ і GENERIC_WRITE а так само їхню комбінацію для дозволу чи читання запису у файл.

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

Параметр lpSecurityAttributes указує на структуру, що описує захист створюваного об'єкта ядра. Йому може бути привласнене значення NULL.

Параметр dwCreationDistribution визначає дії функції в залежності від того, чи існує уже файл із зазначеним ім'ям.

Ідентифікатор

Файл вже існує

Файл ще не існує

CREATE_NEW

Помилка

Створює файл

CREATE_ALWAYS

Знищує існуючий файл і створює новий

Створює файл

OPEN_EXISTING

Відкриває файл

Помилка

OPEN_ALWAYS

Відкриває файл

Створює файл

TRUNCATE_EXISTING

Відкриває файл і урізує його до нульової довжини

Помилка

Параметр dwFlagsAndAttributes визначає атрибути файлу, якщо він створюється і задає режим роботи з файлом.

Константа

Атрибут файлу

FILE_ATTRIBUTE_ARCHIVE

Архівний

FILE_ATTRIBUTE_HIDDEN

Схований

FILE_ATTRIBUTE_NORMAL

Немає ніяких атрибутів

FILE_ATTRIBUTE_READONLY

Тільки для читання

FILE_ATTRIBUTE_SYSTEM

Системний

FILE_ATTRIBUTE_TEMPORARY

Тимчасовий (збережений у пам'яті, але видаляє не при закритті)

Атрибути файлу можуть комбінуватися за винятком FILE_ATTRIBUTE_NORMAL, що завжди використовується на самоті.

Разом з атрибутами можуть комбінуватися і прапори, що задають режим роботи з файлом.

Прапор

Режим роботи з файлом

FILE_FLAG_NO_BUFFERING

Не здійснювати кэширування і випереджальне читання

FILE_FLAG_RANDOM_ACCESS

Кэширувати як файл довільного доступу

FILE_FLAG_SEQUENTIAL_SCAN

Кэширувати як файл послідовного доступу

FILE_FLAG_WRITE_TROUGH

Не буферизувати операцію запису. Робити запис на диск негайно.

FILE_FLAG_DELETE_ON_CLOSE

Знищити файл при закритті. Корисно комбінувати з атрибутомFILE_ATTRIBUTE_TEMPORARY.

FILE_FLAG_OVERLAPPED

Робота з файлом буде здійснюватися асинхронно. Докладно вивчається в п. 9.4.

Параметр hTemplateFile або дорівнює NULL, або задає описувач відкритого файлу. В другому випадку параметр dwFlagsAndAttributes ігнорується, а зазначений файл використовується як шаблон, тобто використовуються його прапори й атрибути.

У випадку удачі функція CreateFile повертає описувач відкритого файлу як об'єкта ядра. Істотно, що в противному випадку вона повертає не NULL, а INVALID_HANDLE_VALUE.

Для роботи з файлами використовуються наступні функції

Функція

Виконувана дія

ReadFile

Читання. Докладно розглянута в п. 9.4

WriteFile

Запис. Докладно розглянута в п. 9.4

SetFilePointer

Позиціонірування покажчика

SetEndOfFile

Зміна розміру файлу

FlushFileBuffers

Примусовий запис буферів кэширування на диск

LockFile

LockFileEx

Блокування частини файлу від запису іншими потоками.

UnlockFile

UnlockFileEx

Розблокування раніше заблокованої частини файлу

8. Робота з файлами.
 8.4. Асинхронна робота з файлами.

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

Windows’95 не дозволяє організувати асинхронну роботу з файлами, але той же самий асинхронний механізм може використовуватися при роботі з послідовними портами, транспортерами і поштовими скриньками.

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

BOOL ReadFile(

HANDLE hFile, // handle of file to read

LPVOID lpBuffer, // address of buffer that receives data

DWORD nNumberOfBytesToRead, // number of bytes to read

LPDWORD lpNumberOfBytesRead, // address of number of bytes read

LPOVERLAPPED lpOverlapped // address of structure needed for overlapped I/O

);

BOOL WriteFile(

HANDLE hFile, // handle to file to write to

LPCVOID lpBuffer, // pointer to data to write to file

DWORD nNumberOfBytesToWrite, // number of bytes to write

LPDWORD lpNumberOfBytesRead, // pointer to number of bytes written

LPOVERLAPPED lpOverlapped // address of structure needed for overlapped I/O

);

Параметри функції ReadFile мають наступне призначення:

  1. hFile - описувач об'єкта ядра “файл”, отриманий у результаті виклику функції CreateFile
  1. LpBuffer - адреса буфера, у который буде вироблятися читання
  1. nNumberOfBytesToRead - кількість байт, який необхідно прочитати
  1. lpNumberOfBytesRead - адреса перемінної, у якій буде розміщена кількість реальна прочитаних байт. Істотно, що відразу після виконання функції ReadFile, цей параметр не може бути встановлений, тому що операція читання тільки почалася.
  1. lpOverlapped - покажчик на структуру OVERLAPPED, що керує асинхронним уведенням висновком.

typedef struct _OVERLAPPED {

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

HANDLE hEvent;

} OVERLAPPED;

Елементи структури мають наступне значення

Назва елемента

Призначення

Internal

Використовується операційною системою. Зберігає статус завершення операції.

InternalHigh

Використовується операційною системою. Зберігає кількість переданих байт.

Offset

Позиція у файлі, починаючи з який необхідно робити операцію читання (запису)

OffsetHigh

Кількість байт для передачі

HEvent

Описувач події, що відбудеться при завершенні операції читання (запису)

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

Параметри функції WriteFile аналогічні параметрам функції ReadFile.

Схем організації асинхронні читання і записи може бути кілька.

  1. Перед запуском операції створюється об'єкт ядра “подія” (див. п. 6.2.5) і його описувач передається у функцію RedFile (WriteFile) як елемент hEvent параметра lpOverlapped. Програма, виконавши необхідні дії одночасно з операцією передачі даних, викликає одну з функцій чекання (напр. WaitForSingleObject), передаючи їй як параметр описувач події. Виконання програми при цьому припиняється до завершення операції виводу-введення-висновку.
  2. Подія не створюється. Як очікуваний об'єкт виступає сам файл. Його описувач передається у функцію WaitForSingleObject. Цей метод простий і коректний, але не дозволяє робити паралельно кілька операцій виводу-введення-висновку з тим самим файлом.
  3. “Тривожний” асинхронний висновок^-вивід-введення-висновок. Схема побудована на використанні функцій ReadFileEx і WriteFileEx. Як додатковий параметр у ці функції передається адреса функції завершення, що буде викликатися всякий раз при завершенні операції виводу-введення-висновку. Істотно, що ці функції виконуються в тім же самому потоці що і функції файлового введення/висновку. Це значить, що потік, що запустив операції читання запису повинний звернутися функцію чекання, щоб дозволити системі викликати функцію завершення.

8. Робота з файлами.
 8.5. Файлова структура NTFS.

·  Системні файли NTFS

Файлова структура NTFS розроблена на зміну системам FAT і HPFS з метою підвищення продуктивності, надійності і сумісності. Вона так само підтримує механізми захисту, необхідні для використання на файлі-сервері мережі.

Любою розподілений сектор NTFS належить якому-небудь файлу. Це відноситься навіть до внутрішніх структур даних. Системою використовуються наступні файли:

Master File Table

$Mft

Список умісту тому

Master File Table2

$MftMirr

Дзеркальне відображення Master File Table

Log File

$LogFile

Протокол останніх операцій з файловою структурою

Volume

$Volume

Ім'я, версія й інша інформація про том

Attribute Definitions

$AttrDef

Таблиця імен, номерів і опису атрибутів

Root Filename Index

$.

Корнєвої каталог

Cluster Bitmap

$Bitmap

Бітова карта розподілу кластерів

Boot File

$Boot

Завантажувальний запис тому

Bad Cluster File

$BadClus

Файл, що складається зі збійних кластерів

·  Master File Table (MFT)

Для кожного файлу на томі NTFS існує спеціальний запис у MFT. Перші 16 записів MFT зарезервовані для спеціального використання. Перший запис описує саму MFT, а друга - її копію MFT2. Початок області даних MFT і MFT2 записано в завантажувальному секторі, розташованому на початку диска. Копія завантажувального сектора зберігається в середині диска. Третій запис визначає Log File (див.п.9.5.3), використовуваний для відновлення файлової структури у випадку збоїв. Починаючи із сімнадцятого запису в MFT міститься інформація про каталоги і файли тому.

Кожен запис у MFT займає досить велике місце. Невеликі файли (до 1500 байт) містяться усередині цього запису і не вимагають для збереження додаткового місця на диску.

Такий спосіб збереження файлів значно прискорює доступ до них. У випадку, якщо файл не міститься усередині одного запису, у MFT міститься інформація про розташування файлу. Невеликі каталоги так само розміщаються усередині одного запису MFT. У противному випадку вони організуються у виді B-дерева.

·  Цілісність даних і здатність до самовідновлення.

Існує три види файлових структур

·  1. Careful-write file systems - файлові системи, у яких для підтримки цілісності запис на диск відбувається негайно з появою запиту на запис. Приклад FAT у MS DOS.

·  2. Lazy-write file systems - файлові системи, у яких для підвищення продуктивності виробляється кеширування даних. У випадку краху системи дані в кеш можуть бути загублені, а цілісність файлової структури - порушена. Приклад: FAT у Windows NT і більшість структур у UNIX.

·  3. Recoverable file systems - файлові системи, що поряд з кешируванням, що підвищує продуктивність, застосовують спеціальні засоби підтримки цілісності даних і здатні до самовідновлення після краху системи. До таких систем відноситься NTFS.

Кожна операція, що змінює вміст тому NTFS розглядається як транзакція і може бути розбита на послідовність елементарних дій. Коли виробляється операція зміни вмісту будь-якого файлу, у файл протоколу (Log file)заноситься наступна інформація:

·  Яким образом можна повторити транзакцію (redo)

·  Яким образом можна скасувати транзакцію (undo)

Крім цього, кожних кілька секунд Windows NT перевіряє дисковий кеш на предмет виконання операцій запису і заносить відповідні мітки в Log file.

При кожнім завантаженні операційної системи відбувається перевірка коректності завершення її роботи. У випадку, якщо робота системи завершилася крахом, виробляються дії по відновленню файлової структури. При цьому використовується інформація, записана в Log file.

·  Організація і керування дисками

При організації і керуванні дисками в Windows NT можна використовувати наступні можливості:

·  Можливість використання декількох фізичних дисків. При цьому допускається як розбивка кожного фізичного диска на розділи (volume sets), так і розміщення одного роздягнула вроздріб на декількох фізичних дисках (stripe sets).

·  Можливість використання спеціальних механізмів захисту від збоїв (fault-tolerance options)

·  Можливість використання сервісу збереження, відновлення даних і взаємодії з джерелами безперебійного харчування.

Кожен фізичний диск може бути розбитий максимум на чотири розділи. Розділи можуть бути основними (primary) і розширеними (extended). Основний розділ може містити код завантаження операційної системи. Розширений розділ може бути додатково розбитий на підрозділи. Кожному розділу і підрозділу операційна система ставить у відповідність логічний диск і призначає своє ім'я (C:, D:, E: і т.д.)

Крім розбивки фізичного диска на розділи, система дозволяє один логічний диск вроздріб на декількох фізичних. Розділи різних фізичних дисків збираються в один логічний диск. Це збільшує продуктивність дискової підсистеми.

Наступні прийоми використовуються для захисту від збоїв:

·  Дзеркальне відображення дисків (disk mirroring). Цей метод використовує два різних фізичних диски, приєднаних до одного контролера і діє на рівні розділів. Дані одного розділу автоматично копіюються в інший розділ, розміщений на іншому фізичному диску. Ця резервна копія використовується у випадку відмовлення першого диска. При цьому не потрібно, щоб обидва розділи мали однакові фізичні характеристики (кількість доріжок, секторів і т.д.).

·  Подвоєння дисків (disk duplexing) цілком аналогічно дзеркальному відображенню, за винятком того, що використовуються не тільки різні фізичні диски, але і різні контролери. Для Windows NT дзеркальне відображення і подвоєння дисків нерозрізнені.

·  Розміщення одного роздягнула на декількох дисках з контролем парності (Disk striping with parity). Цей метод побудований на основі простого розміщення одного роздягнула на декількох дисках і відрізняється тим, що один розділ на кожнім фізичному диску виділяється для збереження контрольних сум.