Введення в файлові системи UNIX, Unix, Операційні системи, статті

Станіслав Лапшанскій

Стаття є перекладом тексту Dru Lavigne Understanding Unix Filesystems

В першій статті циклу ми розглядали вміст BIOS’овской і Unix’ов таблиць розділів за допомогою, відповідно утиліт fdisk і disklabel. У цій статті ми продовжимо розмову і розглянемо використання утиліти newfs, а так же поговоримо про індексних таблицях.

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

Існують два способи форматування жорстких дисків. Коли ви купуєте новий жорсткий диск, то в більшості випадків він поставляється вже відформатованим на низькому рівні (low level format). За допомогою низькорівневого форматування на диску створюються треки і сектора, в парі вони створюють простір адресуються фізичних блоків по 512 байт.

Другим способом форматування, як неважко здогадатися, є високорівневе (high level) форматування. Під час такого форматування за допомогою таких утиліт як format (у системі DOS) або newfs (В системі FreeBSD), на розділі жорсткого диска якраз і створюється певна файлова система. Прикладами файлових систем можуть служити FAT16, FAT32, NTFS і FFS. Різні файлові системи можуть відрізнятися по цілому ряду показників – наприклад по продуктивності, проте як мінімум дві функції збігаються у всіх файлових систем: Кожна файлова система має таблицю для відображення файлів з даними користувача на фізичні блоки вінчестера. Файлова система може використовувати свою «логічну» адресацію блоків, для того що б намагатися оптимізувати продуктивність запитів вводу-виводу.

Давайте уявимо, що ви є файловою системою. Ваша мета – швидко зберігати (записати) і знаходити (читати) дані. На вас діють наступні обмеження:

  1. Ви маєте доступ до площі, званою циліндром.
  2. Ваш циліндр має 255 горизонтальних рядків (треки) і 63 вертикальних стовпців, які називаються секторами.
  3. На перетині цих рядків знаходяться блоки в яких ви можете зберігати по 512 байт даних.

Отже, підрахуємо, скільки блоків міститься на циліндрі:

255 * 63 = 16,065

Якщо ви помістіть по одному файлу в кожен блок, то ви зможете зберегти 16065 файлів. Якщо ви намалюєте для себе табличку і пронумеруете її рядки від 1 до 16065, то тоді ви просто зможете записувати ім’я кожного нового файлу поруч з будь-яким вільним номером, виходить так, як ніби ви записуєте файл в блок з цим номером. Якщо ви видаляєте файл, не забудьте стерти його ім’я з вашої таблиці. Коли ви захочете перемістити який-небудь файл, знайдіть його в таблиці, зітріть його, а потім запишіть його ім’я поруч з новим номером блоку. Ви повинно бути швидко зрозумієте, що можна не обтяжувати себе проблемами пов’язаними з фізичним переміщенням файлу з одного блоку в інший, оскільки значно простіше змінити запис про фото у вашій таблиці.

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

На жаль простота призводить до вкрай нераціонального використання дискового простору. Справа в тому, що запис файлів в 512 байтним блоки призводить до відмінних результатів, коли всі файли мають розміри 512 байт. Однак життєвий досвід підказує нам, що файли мають найрізноманітніші розміри, від декількох байт до сотень мегабайт.

Поставте себе на місце файлової системи і подумайте, як ви запишете файл розміром 10 байт. Якщо просто помістити цей файл в блок жорсткого диска, то ви втратите 412 байт корисного простору. Зберігши велика кількість маленьких файлів ви відправите в сміття цілу купу вільного місця. Що станеться, якщо ви запишете на диск 16065 файлів розміром 1 байт? Ви використовуєте всі наявні у вас блоки жорсткого диска записавши всього 16065 байт корисних даних. Незважаючи несколькомегабайтний розмір циліндра на вашому жорсткому диску, ви не зможете знайти жодного вільного блоку для ваших файлів. Це так звана ситуація відсутності індексних елементів (або відсутності місця в індексному таблиці, що теж саме). Очевидно, що виникнення такої ситуації в реальних умовах вкрай небажано.

Продовжуючи думати як файлова система, можна прийти до висновку, що має сенс не віддавати цілий блок для одного маленького файлу. Однак, зараз саме час подумати яким чином ви організуєте вашу таблицю в умовах того, що в одному блоці може бути більше одного файлу. Якщо ви просто почнете набивати в блок стільки файлів, скільки можна розмістити в 512 байтах, то яким чином ви будете відслідковувати де закінчується один файл і починається інший? Що буде, якщо ви видалите файл розміром 10 байт, а на його місце запишіть файл розміром 8 байт і куди ви запишіть інформацію про залишилися 2 байтах в разі якщо ви захочете записати туди два однобайтових файлу? Відразу видно, що подібна схема швидко втрачає працездатність.

Більшість файлових систем користуються концепцією фрагментації. Фрагмент це логічна частина блоку. Кожен фрагмент може бути адресований, тобто про нього може бути зроблено запис в індексному таблиці. Наприклад файлова система може розбивати кожен блок на чотири фрагменти. Таким чином кількість доступних блоків множиться на чотири, одночасно зменшуючи їх розмір в чотири рази. Наприклад якщо спочатку було доступно 16065 блоків, по 512 байт в кожному, то після такої фрагментації їх кількість зросте до 64 260, при розмірі блоку 128 байт. Кожен фрагмент може інтерпретуватися як блок для зберігання даних і, таким чином, може містити один файл, отже тепер в індексному таблиці 64260 елементів і при цьому немає необхідності турбуватися про те, як відслідковувати декілька файлів в одному логічному блоці.

Давайте подивимося що у нас знаходиться на іншій чаші ваг. Що станеться, якщо вам знадобиться записувати файли розмір яких більше ніж розмір фізичного або логічного блоку даних? Для збереження на диску такого файлу, вам, зрозуміло, доведеться задіяти більше одного блоку даних. Припустимо, що ви хочете зберегти файл об’ємом 1000 байт. Для цього будуть потрібні дві фізичні блоку по 512 байт, і відповідно у вашій індексного таблиці будуть два записи. Вам також доведеться подумати над тим, як вносити туди ці записи, оскільки тепер важливий їх порядок їх внесення. У даній ситуації недостатньо просто знати, що файл знаходиться, скажімо, в блоках 3 і 4. Вам обов’язково треба бути впевненими, що перші 512 байт файлу знаходяться саме в блоці номер три, а решта в четвертому блоці.

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

Ось кілька речей, які можуть збільшити швидкодію операцій читання. По-перше це збільшення логічного блоку даних таким чином, що б він включав в себе відразу кілька фізичних блоків. Коли користувач захоче звернутися до файлу, який міститься у фізичному блоці, в оперативну пам’ять завантажиться цілий логічний блок. Таким чином економиться велика кількість звернень до диску за окремими фізичними блоками. Якщо кілька блоків буде додано в оперативну пам’ять, то досить імовірно, що всі дані, які запитував користувач будуть передані за один раз.

Давайте підсумуємо все, те, про що ми говорили, обговорюючи файлову систему:

  1. Вона являє собою кінцеве кількість блоків для зберігання даних, які пов’язані з адресуються списком, який в файлових системах для операційних систем UNIX має назву «індексний таблиця».
  2. Якщо ви вичерпує число елементів цієї таблиці і тим самим, число доступних блоків даних, то ви не можете створювати нові файли, незважаючи на те, скільки вільного місця на вашому диску.
  3. Якщо ви припускаєте збереження великої кількості маленьких файлів, вам необхідно фрагментувати блоки даних, для того що б збільшити розмір індексного таблиці.
  4. Однак якщо ви хочете збільшити продуктивність операції читання, вам необхідно збільшити розмір логічного блоку даних, для того що б за одну операцію читання в пам’ять зчитується більше даних.

Тепер давайте подивимось як все вищевикладене застосовно до FreeBSD. Коли ви користуйтеся утилітою newfs, ви форматуєте ваш слайс в файлову систему FFS (Berkeley Fast File System – швидка файлова система Берклі). Давайте подивимося шматочки з сторінки керівництва по утиліті newfs, для того що б дізнатися, які установки «за замовчуванням» передбачені для цієї файлової системи:

man 8 newfs

Нас цікавлять тільки деякі ключі. Почнемо з ключа «-b»:

 -B размер_блока

Вказує розмір блоку у файловій системі в байтах. Він повинен бути ступенем числа 2. За замовчуванням розмір 8192 байта. Найменший можливий розмір 4096 байтів.

Зверніть увагу, що це розмір блоку файлової системи. Фізичний блок завжди має розмір 512 байтів. 8192 байти це насправді 16 фізичних блоків. Таким чином цей параметр задає розмір логічного блоку, тобто який обсяг даних буде лічений в оперативну пам’ять за один раз. Пам’ятайте, що цей параметр створений для збільшення швидкості читання і є однією з причин, чому в назві файлової системи FreeBSD присутнє слово «швидкий».

Ключ «-f»:

 -F размер_фрагмента

Вказує розмір фрагмента файлової системи в байтах. Значення має лежати в межах від размер_блока / 8 до размер_блока і бути ступенем числа 2. За замовчуванням використовується розмір 1024 байта.

FFS використовує фрагментованість, проте фрагментіруется логічний, а не фізичний блок. За замовчуванням розмір фрагмента дорівнює двом фізичним блокам.

Тепер розглянемо ключ «-i»:

 -I количество_байт_на_элемент_индексной_таблицы

Вказує щільність індексних записів у файловій системі. За замовчуванням створюється по запису на кожні 4 * размер_фрагмента байт простору даних. Для того, щоб створити побільше елементів таблиці, треба задавати відповідно великий параметр і, навпаки. Для одного файлу необхідний один елемент таблиці, таким чином цей параметр визначає середній розмір файлів у файловій системі.

За замовчуванням один запис у таблиці створюється на кожні 4048 байт дискового простору і кожен файл має свій номер запису. Оскільки кожен запис відповідає одному файлу, то середній розмір файлу у файловій системі передбачається 4048 байт.

Ось ще два параметри, про які слід тут згадати, оскільки вони впливають на продуктивність операція читання / запису файлової системи FFS. По-перше ключ-m:

 -M свободное_место%

Відсоток вільного місця резервується на файловій системі, тобто поріг мінімального вільного простору. Значення за замовчуванням, визначається константою MINFREE модуля . В даний час це значення дорівнює 8%. Читайте man 8 tunefs для повного опису цього параметра.

Продуктивність будь файлової системи починає «просідати», коли їй не вистачає вільних блоків для зберігання даних. Справа в тому, що файлові системи «воліють» зберігати файли одного каталогу в суміжних блоках (тобто поруч один з одним), а це стає скрутним, коли кількість вільних блоків зменшується і системі доводиться витрачати час на їх пошук. Творці FFS вказують, що її продуктивність різко падає, коли диск заповнюється на більш ніж 90%. Коли файлова система досягає порогу встановленого для обсягу вільного місця (за умовчанням 8%), для звичайних користувачів відбувається блокування запису будь-яких файлів. Користувачі будуть отримувати повідомлення про помилку, і ймовірно нагадають адміністратору про сформовану ситуацію. Суперкористувач зберігає можливість запису інформації на диск і використання залишилися вільними блоків, однак у цей момент краще зайнятися розробкою плану порятунку файлової системи, а не чекати поки на ній скінчиться місце.

Тепер давайте розберемося з другим ключем, що мають справу з вільним місцем:

 -O способ_оптімізаціі

Варіанти – «space» і «time». Файлова система може або намагатися зменшити час, необхідний для виділення блоків даних, або спробувати мінімізувати фрагментацію дискового простору. Якщо значення параметра minfree (див. вище), менше 8%, то за замовчуванням приймається оптимізація по фрагментації (space), а якщо більше або дорівнює 8%, файлова система намагається оптимізувати час доступу (Time). Для повного опису цього параметра почитайте man 8 tunefs.

Більшість файлових систем використовують спеціальні алгоритми для того що б визначити, які файли повинні займати які блоки на диску. Цей ключ використовується для визначення якої стратегії оптимізації повинен дотримуватися алгоритм FFS для розміщення файлів. У ситуації достатку вільного дискового простору можна використовувати оптимізацію по швидкості (time). Однак коли обсяг вільного місця на диску переходить межу визначається ключем «-m», оптимізація фрагментації (space) стає більш важливим завданням, ніж швидкість.

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

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

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*