- •Логічна організація файлових систем
- •11.1. Поняття файла і файлової системи
- •11.1.1. Поняття файла
- •11.1.2. Поняття файлової системи
- •11.1.3. Типи файлів
- •11.1.4. Імена файлів
- •11.2. Організація інформації у файловій системі
- •11.2.1. Розділи
- •11.2.2 Каталоги
- •11.2.3. Зв’язок розділів і структури каталогів
- •11.3. Зв’язки
- •11.3.1. Жорсткі зв’язки
- •11.3.2. Символічні зв’язки
- •11.4. Атрибути файлів
- •11.5. Операції над файлами і каталогами
- •11.5.1. Підходи до використання файлів процесами
- •11.5.2. Загальні відомості про файлові операції
- •11.5.3. Файлові операції posix
- •11.5,4. Файлові операції Win32 api
- •11.5.5. Операції над каталогами
- •11.6. Міжпроцесова взаємодія на основі інтерфейсу файлової системи
- •11.6.1. Файлові блокування
- •11.6.2. Файли, що відображаються у пам’ять
- •11.6.3. Поіменовані канали
- •Висновки
- •Контрольні запитання та завдання
11.6.2. Файли, що відображаються у пам’ять
Цей розділ присвячено реалізації відображуваної пам’яті на основі інтерфейсу файлової системи. Після відображення доступ до такої пам’яті спричиняє виконання операцій доступу до вмісту відображеного файла. Таку технологію широко застосовують у сучасних операційних системах — в UNIX вона визначена стандартом POSIX, у лінії Windows ХР її реалізація доступна через Win32 АРІ.
Принципи дії відображуваної пам’яті.
Інтерфейс відображуваної пам’яті POSIX
Відображення файлів у пам’ять відбувається за допомогою спеціального системного виклику; у POSIX такий виклик визначений як mmap( ). Він призводить до того, що у визначену частину адресного простору процесу відображають заданий файл або його частину. Після виконання цього системного виклику доступ до такої пам’яті спричинятиме прямий доступ до вмісту цього файла (читання пам’яті аналогічне до читання із файла, її зміна аналогічна до зміни файла). Перед використанням цього виклику файл має бути відкритий.
Відображення в цьому разі працює так. Коли файл відобразився на ділянку пам’яті, що починається з адреси р, то:
♦ у разі доступу до байта пам’яті за адресою р буде отримано нульовий (початковий) байт цього файла;
♦ у разі зміни байта пам’яті за адресою p+(N байт) буде змінено N-й байт файла (починаючи від 0);
♦ доступ до пам’яті за кінцем файла неможливий і призводить до помилки.
У разі закриття файла або завершення роботи процесу модифіковану інформацію зберігають у файлі на диску.
Загальний принцип відображення файла в адресний простір процесу показано на рис. 11.2.
Рис. 11.2. Файл, що відображається у пам'ять
Системний виклик mmap( ) відповідно до POSIX має такий синтаксис:
де: start — адреса, з якої почнеться відображувана ділянка (найчастіше цей параметр покладають рівним NULL, надаючи ОС самій визначити, за якою адресою почати відображення);
len — розмір відображуваної ділянки у байтах;
prot — режим доступу до відображуваної пам’яті (PR0T_READ — дозволене читання, PR0T_WRITE — дозволене записування);
flags — прапорці відображення (MAP_SHARED — усі зміни мають бути негайно записані у відображуваний файл без буферизації, MAP_PRIVATE — під час записування в ділянку буде створено копію відображуваного файла, і подальші зміни відбуватимуться з нею);
fdl - дескриптор відображуваного файла;
offset — зсув у файлі, із якого почнеться відображення.
Результатом виклику mmap( ) буде адреса, з якої почате відображення.
Розрив відображення трапляється у разі використання системного виклику, що у POSIX визначений як munmap( ), після чого відповідна ділянка пам’яті більше не буде пов’язана із файлом, і спроба доступу до неї спричинить помилку. Розрив відображення теж призводить до збереження інформації у відповідному файлі.
При завершенні програми необхідності явного виклику munmap( ) немає — записування змін на диск виконуватиметься автоматично.
У разі використання відображуваної пам’яті необхідно виконати такі дії.
1.Відкрити файл із режимом, відповідним до того, як потрібно цей файл використовувати (найкраще — для читання і записування):
2.Якщо це новий файл, задати його довжину за допомогою 1seek( ) і write( ):
3.Відобразити файл у пам’ять:
4.Закрити дескриптор файла:
5. Організувати доступ до файла через відображувану пам’ять:
6. Якщо відображення більше не потрібне — скасувати його:
Під час роботи із відображуваною пам’яттю застосування може отримувати сигнали SIGSEGV (у разі спроби записати у пам’ять, відкриту тільки для читання) і SIGBUS (у разі спроби доступу до ділянки за межами відображення, наприклад, за кінцем файла).
Мїжпроцесова взаємодія на основі відображуваної пам’яті POSiX
Кілька процесів можуть відобразити у свої адресні простори той самий файл (якщо задано режим відображення МЛР_ SHARED). Зміни у відображеній пам’яті, зроблені одним із цих процесів, будуть негайно видимі в усіх інших. Таким чином реалізують розподілювану пам’ять.
Наведемо приклад обміну даними між процесами за допомогою відображуваної пам’яті. Одне із застосувань буде сервером і очікуватиме змін, зроблених клієнтом.
Клієнт буде подвоювати значення у відображуваній пам’яті.
У разі використання відображуваної пам'яті для міжпроцесової взаємодії потрібно забезпечувати синхронізацію доступу до неї. Для цього можна використати засоби міжпроцесової синхронізації, наприклад файлові блокування.
Особливості інтерфейсу відображуваної пам’яті Win32 АРІ
Як параметр у функцію відображення файла в пам’ять (у Win32 АРІ її називають MapViewOfFile( )) передають не дескриптор відкритого файла, як у mmap( ), а дескриптор спеціального об'єкта відображення, що створюється заздалегідь за допомогою функції CreateFileMapping( ). Під час створення об’єкта відображення вказують дескриптор відкритого файла; далі цей об’єкт можна використовувати для відображення кількох регіонів одного файла.
Розглянемо особливості функції CreateFileMapping( ):
де: hf — дескриптор файла, відкритого для читання (а можливо, і для записування);
prot - режим доступу до пам’яті (PAGE_READWRIТЕ - розподілений доступ для читання і записування, аналогічний до MAP_SHARED, PAGE_WRITECOPY — копіювання під час записування, аналогічне до MAP_PRIVATE);
size_low. size_high — розмір файла (може дорівнювати нулю, у цьому разі розмір відображення буде рівним поточному розміру файла, size high використовують, коли файл за розміром більший за 232 байти);
mapname - ім’я відображення.
CreateFileMapping( ) повертає дескриптор об’єкта відображення.
Якщо файл займає менше місця, ніж задано за допомогою параметрів size_1ow і size_high, його автоматично розширюють до потрібного розміру без необхідності виклику аналогів 1seek( ) і write( ).
Після створення об’єкта відображення необхідно на його основі задати відображення у пам’ять за допомогою MapViewOfFile( ):
де: fmap - дескриптор об’єкта відображення;
prot - режим відображення (FIL E_MAP_WR І ТЕ — доступ для записування, потребує задання PAGE_READWRITE для об’єкта відображення, FILЕ_МАР_С0РY - копіювання під час записування, потребує задання PAGE_WRITECOPY);
off_1ow, off_high - зсув відображуваного регіону від початку файла (має бути
кратним 64 Кбайт);
1en — довжина відображуваного регіону у байтах (якщо 1еп=0, відображають ділянку до кінця файла).
Ця функція повертає покажчик на початок відображеної ділянки пам’яті. Аналогом nunmap( ) є функція UnmapVlewOfFile( ):
де start - початкова адреса ділянки відображення.
Після використання дескриптор файла і дескриптор об’єкта відображення потрібно закрити за допомогою CloseHandlе( ). Дескриптор файла можна закрити і до виклику MapViewOfFile( ).
Для роботи з відображуваною пам’яттю у Win32 необхідно.
1.Відкрита файл, звичайно для читання і для записування:
2.Створити об’єкт відображення для файлу:
3.Закрити файл:
4.Відобразити файл або його фрагмент у пам’ять:
5.Організувати доступ до файла через відображувану пам’ять:
6.Якщо відображення більше не потрібне — закрити відповідний дескриптор:
Реалізація розподілюваної пам’яті у Win32 АРІ
Ґрунтуючись на підтримці відображуваної пам’яті у Win32 АРІ, легко реалізува¬ти розподіл пам’яті між процесами. Це зумовлено низкою можливостей, пов’я¬заних із наявністю окремих об’єктів відображення.
♦ Можна задавати об’єкти відображення, які використовують не конкретний дисковий файл, а файл підкачування; для цього достатньо передати у функцію CreateFi1еМарріng( ) замість дескриптора файла значення ІNVALID_HANDLE_VALUE (-1).
Це позбавляє програміста необхідності створювати файл тільки для обміну даними з іншим процесом (як потрібно у POSIX).
♦ Об’єктам відображення під час їхнього створення можна давати імена, після чого вони можуть використовуватися кількома процесами: перший створює об’єкт і задає його ім’я (як параметр CreateFi1еМарріng( )), а інші відкривають його за допомогою функції OpenFilєМарріng( ), передавши як параметр те саме ім’я.
Функцію OpenFilеМарріng( ) використовують для отримання доступу до наявного об’єкта відображення:
де: prot — аналогічний відповідному параметру MapViewOfFile( );
name — ім’я об’єкта відображення.
Приклад обміну даними між клієнтом і сервером, аналогічний до прикладу для відображуваної пам’яті POSIX, наведено нижче.
Особливості реалізації відображуваної пам’яті
Практична реалізація відображуваної пам’яті звичайно спирається на функції менеджера віртуальної пам’яті. У разі відображення файла у пам’ять створюють зв’язок між файлом і пам’яттю, аналогічний до того, що задають між пам’яттю і файлом підкачування під час завантаження сторінок на вимогу. За першої спроби доступу до такої пам’яті відбувається сторінкове переривання, оброблювач якого завантажує сторінки із файла безпосередньо у пам’ять (в адресний простір процесу). Під час записування відповідну сторінку пам’яті позначають як модифіковану, подальша робота з нею відбувається аналогічно до роботи зі звичайною модифікованою сторінкою у разі підкачування (наприклад, якщо відбувається заміщення, її автоматично збережуть у файлі).
Переваги й недоліки відображуваної пам'яті
Наведемо переваги використання файлів, що відображаються у пам’ять.
♦ Робота із такими файлами зводиться до прямого звертання до пам’яті через покажчики, ніби файл був частиною адресного простору процесу. Під час роботи зі звичайними файлами для виконання одних і тих самих дій потрібно відкривати файл, переміщувати покажчик поточної позиції, виконувати читання і записування та закривати файл.
♦ Робота із відображуваними файлами може бути реалізована ефективніше. Це пов’язано з тим, що:
для роботи з ними достатньо виконати один системний виклик (mmap( ) або MapViewOfFile( )), а далі працювати із ділянкою пам’яті в адресному просторі процесу; водночас для відкриття файла, читання, записування тощо потрібно виконувати окремі системні виклики;
не потрібно копіювати дані між системною пам’яттю і буфером режиму користувача, що необхідно для звичайних операцій читання і записування файла — у разі використання цієї технології файл безпосередньо відображається на адресний простір процесу.
♦ За допомогою відображуваних файлів можна легко реалізувати розподіл пам’яті між процесами, якщо відобразити один і той самий файл на адресний простір кількох із них.
Головним недоліком цієї технології є те, що відображуваний файл не може бути розширений позиціюванням покажчика поточної позиції за його кінець і виконанням операції записування (через те, що підсистема віртуальної пам’яті у цьому випадку не може визначити точну довжину файла).
Приклади використання відображуваної пам’яті
Назвемо деякі підходи до використання відображуваної пам’яті на рівні операційної системи.
♦ Відображення файла у пам’ять може використати для завантаження виконуваних файлів у пам’ять (такі файли відображаються в адресний простір процесу і є простором підтримки для сторінок коду). Про приклад використання такої технології у Windows ХР ішлося раніше. За таким самим принципом завантажують виконувані файли в Linux.
♦ На основі відображуваної пам’яті можна також реалізувати кешування диска; про такий підхід ітиметься пізніше.
♦ За допомогою цієї технології можна виділяти пам’ять процесу. Для цього в його адресний простір відображають спеціальний файл, у разі доступу до якого завжди повертають нулі. В UNIX його називають /dev/zero.
♦ Можна забезпечити автоматичне збереження значень складних структур даних між викликами програми (такі структури створюють у ділянці пам’яті, що відповідає відображеному файлу; під час наступних викликів цей файл відображають у ту саму ділянку пам’яті знову, і всі структури поновлюються в цій пам’яті повністю).
