Глава 9. Физика файловых систем

Введение в POSIX'ивизм
(C) Алексей Федорчук, 2005

Назад Содержание Вперед

Глава 9. Физика файловых систем

Файловая система - один из самых многозначных терминов в околокомпьютерной литературе. Им обозначается и подсистема ядра, отвечающая за управление операциями с файлами, и способ физической организации данных на носителях, и логическая структура файлов и каталогов. В настоящий момент нас будут интересовать два последних понятия. В этой главе мы рассмотрим физику размещения файлов, а логику их организации отложим до главы следующей.

Содержание

Дисковые накопители

В современных операционках POSIX-семейства поддерживается множество файловых систем. В первом приближении их можно разделить на две группы - реальные, или базирующиеся на дисках (точнее, на блочных устройствах, block based file systems), и виртуальные, под которыми никаких реальных физических устройств не обнаруживается. Есть и промежуточный вид файловых систем - на виртуальных дисках в оперативной памяти (т.н. RAM-дисках). Основным предметом нашего рассмотрения будут файловые системы первой группы - о виртуальных файловых системах я скажу несколько слов под занавес.

Как следует из названия, block based файловые системы размещаются на блочных устройствах, в качестве которых выступают обычно диски и их разделы. И потому рассмотрению ФС этого типа следует предпослать введение о дисковых накопителях.

Дабы не повторять это в дальнейшем, сразу оговорюсь, что почти все сказанное далее относится к дискам с интерфейсом IDE (ATA). SCSI-диски имеют свою специфику, но я с ними дела не имел и собственных впечатлений на сей предмет у меня нет. Да и для пользователя, с ростом объема и скорости ATA-дисков, падением их цены и распространением внешних накопителей с USB- и FireWire-интерфейсами, SCSI становится все менее актуальным. Хотя эту тему и придется затронуть - но не в отношении дисков, а устройств иного типа. Ибо и в Linux, и BSD-системах все не-ATA накопители почему-то любят прикидываться SCSI-устройствами...

Для начала вспомним, что дисковые накопители, как и любые другие устройства, в любой POSIX-совместимой системе предстают перед пользователем в виде файлов специального типа - файлов устройств. Файлы эти расположены в каталоге /dev, и номенклатура их подчиняется правилам, своим для каждого представителя этого семейства ОСей.

В Linux ATA-диски традиционно именовались как /dev/hd?, где hd - общее имя устройств этого класса (рискну предположить, происходящее от hard disk), а символ ? - литера, идентифицирующая конкретный его представитель (табл. 1).

Таблица 1. Номенклатура дисковых накопителей в Linux
Файл Накопитель
/dev/hda Master на 1-м IDE-канале
/dev/hdb Slave на 1-м IDE-канале
/dev/hdc Master на 2-м IDE-канале
/dev/hdd Slave на 2-м IDE-канале

Номенклатура устройств - статична, то есть не зависит от физического их наличия: диск, подключенный как Slave ко второй линии встроенного IDE-контроллера, всегда будет именоваться /dev/hdd, даже являясь единственным накопителем в системе (случай чисто гипотетический - трудно представить себе реальные основания для конфигурации такого рода).

Отдельно следует оговорить, что тем же правилам подчиняется именование не только дисков, но и других накопителей с интерфейсом ATA - CD ROM/R/RW, DVD любого вида или отходящих в прошлое внутренних Zip-приводов.

Однако в последнее время большинство "прогрессивных" дистрибутивов используют файловую систему устройств (devfs), вносящую свои коррективы в номенклатуру устройств, в том числе и дисковых.

При использовании devfs для файлов любых ATA-накопителей предназначен каталог /dev/ide (в некоторых дистрибутивах файловая система устройств монтируется в каталог /devices, а каталог /dev сохраняется для совместимости). Файлы накопителей на встроенном основном IDE-контроллере локализуются в подкаталоге /dev/ide/host0 (если используется еще и дополнительный IDE-контроллер, встроенный или внешний, можно увидеть и каталог /dev/ide/host1). А внутри него есть два подкаталога, соответствующие IDE-каналам - /dev/ide/host{/bus0,/bus1}, каждый из которых опять же может делиться надвое - на каталоги target0 и target1, по количеству подключенных устройств. Внутри каталога target0(1) имеется минимум еще один подкаталог lun0. А уж в нем размещаются непосредственно файл дискового устройства - disc.

Таким образом, полное обозначение дискового раздела будет выглядеть как

/dev/ide/host0/bus0/target0/lun0/disc

для первого диска на первом канале основного IDE-контроллера.

Как и в случае старой номенклатуры, правила ее распространяются и на не-дисковые ATA-накопители, в частности, CD. С той только разницей, что именование CD-привода в этой нотации (назовем ее полной) будет выглядеть так:

/dev/ide/host0/bus1/target0/lun0/cd

Предусмотрен и более краткий способ обращения к файлам устройств - через символические (изредка - жесткие) ссылки; назовем этот способ краткой нотацией. Для файлов дисковых накопителей (независимо от интерфейса - IDE или SCSI) они собраны в каталоге /dev/discs (для файлов CD-приводов, например, - в каталоге /dev/cdrom) с подкаталогами disc0, ... , disc#. И потому к приведенному в качестве примера диску можно обратиться и так:

/dev/discs/disc0/disc

а CD привод будет именоваться следующим образом:

/dev/cdroms/cdrom0

Краткая нотация имеет динамический характер, то есть первый в порядке подключения диск всегда будет представлен устройством /dev/discs/disc0/disc, а второй - /dev/discs/disc1/disc, вне зависимости от того, на каком канале или в каком качестве (Master или Slave) они реально подключены.

Наконец, для совместимости со старыми временами (и старыми привычками) в большинстве дистрибутивов поддерживается и номенклатура обратной совместимости, принятая до внедрения devfs. То есть все тот же дисковый накопитель из примера можно обозвать просто - /dev/hda.

Таким образом, подключение devfs - не препятствие для использования старой номенклатуры накопителей. Правда, это требует соответствующей настройки демона devfsd (точнее, его конфигурационного файла), отвечающего за обратную совместимость. И, при желании, может быть отменено. В частности, такие дистрибутивы, как CRUX и Archlinux, на стадии установки обратной совместимости не используют - при подготовке дисков здесь именовать их приходится только в новой нотации - краткой или полной, без разницы.

При использовании файловой системы devfs имена файлов создаются только для реально существующих в системе устройств (в том числе, для устройств "горячего" подключения, типа PC-карт или USB-драйвов, - и "на лету"). Поэтому, если в системе имеется только единственное IDE-устройство, скажем, жесткий диск как мастер на первом канале, бесполезно было бы искать файлы устройств с именами, отличными от приведенного в примере. Что удобно, но в некоторых реализациях devfs может создавать сложности. Впрочем, как сказал бы Киса Воробьянинов, к теме, которую я в данный момент представляю, это не относится...

В последнее время в большинстве дистрибутивов Linux, вместо файловой системы устройств, активно внедряется механизм udev (о чем будет говориться далее). При этом происходит возврат к старой номенклатуре устройств, в том числе и дисковых накопителей: /dev/hda и так далее. Однако, как и в devfs, файлы создаются только для реально имеющихся в машине устройств.

Несколько отлична номенклатура накопителей во FreeBSD и DragonFlyBSD. Здесь файлы устройств ATA-дисков именуются в общем виде как ad#. Как нетрудно догадаться, аббревиатура ad происходит от ATA Disk, а # - численный идентификатор, соответствующий номеру конкретного накопителя в порядке его подключения к IDE-разъемам (табл. 2)

Таблица 2. Номенклатура дисковых накопителей во FreeBSD и DragonFlyBSD
Файл Накопитель
/dev/ad0 Master на 1-м IDE-канале
/dev/ad1 Slave на 1-м IDE-канале
/dev/ad2 Master на 2-м IDE-канале
/dev/ad3 Slave на 2-м IDE-канале

Во FreeBSD и DragonFlyBSD по умолчанию также принята статичная нумерация файлов дисковых устройств, хотя это можно изменить при перекомпиляции ядра.

В отличие от Linux, во FreeBSD для приводов CD ROM принята своя номенклатура - файлы этих устройств именуются как /dev/acd0, /dev/acd1 и (если такое реально бывает) так далее, вне зависимости от контроллера, к которому они подключены. Имена SCSI-приводов для компакт-дисков - /dev/cd0 и так далее. Самих по себе устройств с таким интерфейсом в пользовательской машине почти наверняка нет. Однако в этом качестве перед системой предстают обычные ATAPI CD- и DVD-приводы, если в ядре включена поддержка эмуляции SCSI (CAM - Common Access Metod). А она требуется для записи DVD, и, в некоторых случаях, также и CD-дисков.

Во FreeBSD 5-й ветки также используется файловая система устройств devfs. Однако влияния на номенклатуру устройств она не оказывает: все низкуровневые утилиты в этой ОС разрабатываются совместно с ядром, и потому задача обратной совместимости тут не ставится. Единственно, что в каталоге /dev установленной FreeBSD 5-й ветки будут присутствовать только файлы реально имеющихся устройств - например, /dev/ad0 и /dev/acd0. Тогда как в более старых ветвях мы увидели бы также созданные "про запас" файлы /dev/ad0, /dev/ad1 и /dev/ad2, хотя попытка обращения к ним ничего, кроме сообщения об ошибке, и не дала бы.

Наконец, прочие BSD-системы (Net- и OpenBSD) также располагают собственной терминологией в отношении дисковых устройств. Соответствующие им файлы именуются как wd0 и так далее (табл. 3).

Таблица 3. Номенклатура дисковых накопителей в NetBSD и OpenBSD
Файл Накопитель
/dev/wd0 Master на 1-м IDE-канале
/dev/wd1 Slave на 1-м IDE-канале
/dev/wd2 Master на 2-м IDE-канале
/dev/wd3 Slave на 2-м IDE-канале

Причем, в отличие и от Linux, и от FreeBSD, в OpenBSD номенклатура дисков по умолчанию динамична - то есть диски нумеруются по порядку, вне зависимости от линии контроллера и положения на ней (Master или Slave). То есть имена устройств в табл. 3 будут отвечать реальности только при наличии четырех дисков. Хотя, как и во FreeBSD, такой порядок может быть изменен при переконфигурировании ядра.

Жесткие диски - не единственные накопители, которые можно обнаружить в современной машине: все более возрастает роль разного рода сменных носителей, вытеснивших, наконец, из этой ниши аксакала - трехдюймовый дисковод. Накопители такие бывают двух типов - с интерфейсом FireWire и USB. О первых не могу сказать ничего определенного - не только не пользовался, но и даже не видел. А вот USB-драйвы (в просторечии - флэшки) заслуживают нескольких слов.

Потому что это - и есть те устройства из числа распространенных, которые изображают из себя SCSI-диски. И соответствующие им файлы устройств подчиняются правилам, установленным для последних. То есть в Linux по старой (и очень новой - при udev) номенклатуре они будут именоваться как /dev/sda, /dev/sdb и так далее. По новой же в полной нотации - точно как SCSI-диски:

/dev/scsi/host0/bus0/target0/lun0/disc

Впрочем, в краткой нотации USB-привод будет выглядеть обычным винчестером:

/dev/discs/disc1/disc

Во FreeBSD USB-накопители также предстают в качестве SCSI-дисков, и, в соответствие с принятыми здесь правилами, имена соответствующих им файлов устройства будут выглядеть как /dev/da1, /dev/da2 и так далее.

К слову сказать, точно так же, как и флэшки будут обычно выглядеть (и в Linux, и во FreeBSD) и цифровые камеры с USB-интерфейсом, точнее, встроенные в них или съемные носители информации; как, впрочем, и карт-ридеры для чтения последних. Да и именование внешних мобильных винчестеров с USB-интерфейсом (типа Fujitsu HandyDrive) подчиняется тем же правилам.

Теоретически ничто не мешает создавать файловые системы непосредственно на дисковых устройствах. Однако практически так почти никогда не поступают - диски принято делить на разделы (partitions в терминах DOS/Windows и Linux, slices в терминологии FreeBSD). Однако прежде чем говорить о разбиении диска, необходимо сказать

Немного о "геометрии"

Слово "геометрия" в заголовке рубрики взято в кавычки не случайно. Дело в том, что с тех пор, как объем дисков перевалил за 500 с небольшим мегабайт (ограничение старых BIOS персональных, ранее именовавшихся IBM-совместимыми, компьютеров), с реальной их геометрией пользователь никогда не сталкивается. Софт, прошитый в дисковой электронике (т.н. firmware) преобразует ее к виду, доступному восприятию BIOS - на деталях, как именно это делается, останавливаться не буду.

А доступная BIOS геометрия диска описывается в терминах цилиндр/головка/сектор (cylinders/heads/sectors, C/H/S). Фигурально говоря (а, повторяю, все, относящееся к дисковой геометрии, ныне следует понимать исключительно фигурально, аллегорически или метафорически), головки считывают информацию с концентрических магнитных дорожек (tracks), на которые поделена каждая дисковая пластина. Вертикальная совокупность треков с одинаковыми номерами на всех пластинах, составляющих диск как физическое устройство, и образует цилиндр. А сектора нарезают пластину, вместе с ее треками, на радиальные фрагменты, именуемые блоками. То есть это можно представить себе таким образом, что блок лежит на пересечении (в пространстве) цилиндра, трека и сектора.

Число треков и секторов в современных дисках обычно фиксировано (вернее, предстает таковым в BIOS): 255 треков нарезается на 63 сектора каждый, что в совокупности дает 16065 блоков на цилиндр. А количество цилиндров определяется объемом диска (в арифметические вычисления вдаваться не буду). Важно здесь только то, что головки диска механически двигаются синхронно по поверхности всех пластин. То есть если на одной пластине информация считывается с 1-го трека, то и все прочие головки перемещаются на ту же дорожку - каждая на своей пластине.

Повторяю, все это условно - хотя бы потому, что понятие цилиндра в геометрическом смысле слова очень трудно применить к современным дискам, часто не то что однопластинным, а даже, если так можно выразиться, полупластинным (то есть только с одной задействованной стороной единственной пластины). Но разбираться с этой геометрией - дело firmware и BIOS, для нас же интересны именно цилиндры - совокупность треков, к которым осуществляется синхронный доступ, и блоки - минимальные кванты дискового пространства.

Образующие цилиндры треки создаются при первичной заводской разметке диска - т.н. низкоуровневом форматировании. Из сказанного выше очевидно, что доступ к данным в пределах одного цилиндра или группы соседних будет выполнен быстрее, чем к данным, записанным частично на первый и, скажем, на последний цилиндр диска. Этот случай не столь уж невероятен, как может показаться: в DOS'е, где пространство, занятое стертыми файлами, помечается как неиспользуемое, но реально перезаписывается только тогда, когда по настоящему свободное место на диске вообще исчерпано, подобная ситуация вполне могла бы возникнуть.

Так вот, чтобы свести к минимуму вероятность разнесения данных по разобщенным цилиндрам, и придуманы были дисковые разделы (вернее, в том числе и для этого - выделение дисковых разделов преследует множество других целей). В единый раздел объединяется группа смежных цилиндров.

Где кончается один раздел и начинается другой? Резонные люди из Одессы сказали бы, что полиция кончается именно там, где начинается Беня Крик. Однако для нас очевидно, что для каждого из разделов следует хранить сведения о его начале и конце (то есть номера первого и последнего из задействованных в нем цилиндров). Где их хранить? Для ответа на этот вопрос следует обратиться к понятию блока.

Как и треки, дисковые блоки (или физические - есть еще блоки логические, но это относится уже к файловым системам, о которых речь пойдет в следующем параграфе) создаются при низкоуровневом форматировании, и пользователь влиять на них не может. Размер их также всегда одинаков и равен 512 байтам. Вернее, таким он видится BIOS'у персоналки - каков он на самом деле, одному Аллаху ведомо.

Однако то, что обмен данными с диском возможен минимум 512-байтными порциями - объективная реальность, как и то, что любой, сколь угодно маленький, объем информации, записанный на него, будет занимать целый блок - вне зависимости от реального своего размера. То есть мелкие текстовые файлики размером в пару символов (сиречь байт) все равно захватят под себя аж 512 байт, не меньше. С другой стороны, считывание данных блоками по 512 байт будет происходить быстрее, чем если бы при каждом обращении головки к диску данные считывались бы побайтно. Однако и это относится уже к теме файловых систем.

Пока же нас интересен один-единственный блок, образованный первым сектором на первом треке первого цилиндра. Он резервируется под служебную область диска, именуемую главной загрузочной записью (MBR - Master Boot Recodr), которая и считывается BIOS'ом при старте машины. Очевидно, что по прямому назначению MBR используется только в том случае, если диск определен в Setup'е BIOS'а как загрузочный (или просто является единственным в системе). Однако поскольку использование каждого конкретного диска остается на усмотрение пользователя, место под него отводится всегда.

Внутри нулевого блока, помимо прочего (в частности, кода какого-либо начального загрузчика, который может быть туда записан) есть еще один зарезервированный участок. Он предназначен для BIOS'овской таблицы разделов (Partition Table), под которую испокон веков (со времен самой первой IBM PC, кажется) отведено 64 байта. В эту таблицу записываются (или могут быть записаны) данные о разделе (разделах) в определенном, доступном пониманию BIOS'а, формате.

А формат этот предусматривает указание для каждого раздела его стартового блока, размера в байтах, идентификатора типа файловой системы (это, вопреки названию, совсем не то же самое, что файловая система, о которой речь пойдет в одном из последующих параграфов) и (только для одного из разделов) флага активности (то есть помечающего данный раздел как загрузочный). Последнее необходимо для некоторых операционок типа DOS, хотя и Linux'у, и любой BSD-системе флаг этот глубоко безразличен.

Всего информации, необходимой для описания дискового раздела, набегает 16 байт. А поскольку, как мы помним, под всю таблицу разделов этих байт отведено лишь 64, без калькулятора можно подсчитать, что предельное количество разделов на диске - 4. Эти разделы называются первичными или, не совсем точно, физическими. Так как в большинстве случаев такие разделы могут быть также поделены на части - разделы логические (о чем речь впереди).

Повторю еще раз - это относится только к машинам с PC BIOS, то есть обычным персоналкам. На всякого рода PowerPC, Sparc'ах и тому подобных станциях все может быть совсем по другому.

Как можно заметить, в описание раздела входит идентификатор файловой системы. Это - некоторое число (в BSD обычно в десятичном представлении, в Linux'е, например, - в шестнадцатеричном), которое ставится в соответствие с файловой системой операционки, планируемой к размещению на диске. Так, раздел, предназначенный для FreeBSD (и DragonFlyBSD - тип его 4.2BSD), имеет идентификатор 165 (десятичный) или A5 (шестнадцатеричный), раздел для Linux (Linux native) - 131 или 83, соответственно, FAT16 - 6, расширенный раздел (т.н. DOS Extended) - 5, и так далее. В таблице 4 приведены значения наиболее важных для пользователя Linux и BSD-систем идентификаторов типов разделов (по выводу Linux'ового fdisk, то есть в шестнадцатеричном исчислении) с их краткой характеристикой.

Таблица 4. Значения идентификаторов типов разделов
Значение, hex Название Характеристика
1 FAT12 Файловая система DOS-дискет
4 FAT16<32M Файловая система старых (ниже 4-й) версий DOS
5 Extended Расширенный раздел DOS
6 FAT16 Обычный раздел DOS (до 2 Гбайт)
b W95 FAT32 Раздел Windows 95 (от OSR2 и выше)
63 GNU HURD Раздел ОС HURD
81 Minix Раздел ОС Minix, используется на дискетах Linux
82 Linux swap Раздел подкачки Linux
83 Linux Родной (native) раздел Linux
8e Linux LVM Раздел для использования менеджером логических томов
a5 FreeBSD Раздел FreeBSD и DragonFlyBSD (4.2BSD)
a6 OpenBSD Раздел OpenBSD
a8 Darwin UFS Раздел MacOS X
a9 NetBSD Раздел NetBSD
fd Linux raid auto Раздел для использования в программных RAID

Для использования в Linux непосредственно предназначены, кроме Linux native и Linux swap, так же разделы типа Minix (хотя с отмиранием дискет актуальность его теряется), Linux LVM и Linux raid auto. Кроме того, без всяких дополнительных ухищрений возможен доступ из Linux к разделам FAT любого рода. Прочие из перечисленных типов предназначены для одноименных ОС.

Присвоение разделу какого-либо идентификатора не значит, что тем самым на нем волшебным образом возникает соответствующая файловая система. Нет, он используется только программами дисковой разметки, и просто предопределяет, какого рода вторичная таблица разделов (Disk Label) может быть на нем записана. Но тут мы переходим к разговору

Собственно о разделах

Итак, следствием установлено, что на одном физическом диске может быть создано до 4 (включительно) разделов, каждый их которых может быть приписан к отдельной операционной системе. А что дальше? А дальше следует изучить вопрос стилей разметки разделов.

Стили разметки разделов именуются Disk Label, что не следует путать с метками дисков (disk label) - произвольными именами, которые в DOS (и не только) можно присвоить дисковому разделу. Стиль же разметки - это формат вторичной таблицы разделов, записываемой в первый блок раздела первичного. Эта таблица и определяет характер доступных действий над данным первичным разделом.

Пользователи Windows обычно не имеют причин задумываться над проблемой стилей разметки. Однако стилей таких существует немало - чтобы убедиться в этом, достаточно зайти в меню конфигурации ядра Linux, в подраздел Partition Types раздела File systems. Однако я опять забегаю вперед - нынче из всего этого изобилия нас будут интересовать только два стиля разметки - DOS и BSD.

В DOS/Windows используется (как ни удивительно) DOS-стиль разметки разделов. Он основывается на BIOS-таблице, задействованной лишь частично. А именно - из четырех доступных записей Partitions Table заполняются только две (вернее, только два раздела можно создать средствами стандартного FDISK из DOS/Windows 96/98/ME; как обстоит дело в NT/2000/XP - просто не знаю).

В записи для первого раздела можно указать идентификатор типа файловой системы (например, FAT16 или FAT32), второму же разделу автоматически присваивается идентификатор типа Extended DOS. А уж Extended-раздел может быть далее поделен на логические разделы (Logical Partitions). В терминологии DOS/Windows они именуются логическими томами (Logical Volume). Однако мы зарезервируем этот термин для системы LVM (Logical Volumes Manager), разговор о которой пойдет в одной из ближайших интермедий.

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

В Linux также используется DOS-стиль разметки. Только тут уж BIOS-таблица задействуется по полной программе - стандартными средствами этой ОС (Linux'овым fdisk, имеющим весьма мало общего со своим тезкой из DOS/Windows, его front-end'ом (оболочкой) cfdisk или (почти) универсальной программой parted можно создать все четыре первичных раздела и пользовать их в свое удовольствие. Правда, опять же лишь одному из них можно присвоить идентификатор раздела расширенного и, соответственно, поделить на логические разделы.

Разделы в Linux представляются перед системой (и пользователем) в качестве таких же файлов блочных устройств, как и диски. И номенклатура их подчиняется тем же правилам. В старой (до-devfs'ной) нотации к обозначению целого диска (например, /dev/hda) просто добавляется численный идентификатор раздела (его порядковый номер, начиная с единицы. Идентификаторы с 1-го по 4-й зарезервированы за первичными разделами. Если один из них определен как расширенный, то логические разделы внутри него нумеруются, начиная с 5-го (даже если первичных разделов на диске нет и в помине). То есть типичная картина разбиения диска под Linux будет выглядеть примерно так (табл. 5).

Таблица 5. Примерная схема дисковой разметки в Linux
Файл Раздел
/dev/hda1 1-й первичный раздел
/dev/hda2 2-й первичный раздел
/dev/hda3 3-й первичный раздел, определенный как расширенный
/dev/hda5 1-й логический раздел внутри расширенного
/dev/hda6 2-й логический раздел внутри расширенного

При использовании devfs файлы устройств, соответствующих дисковым разделам, именуются part#, где # - порядковый номер (с 1-го по 4-й - для первичных разделов, с 5-го и далее - для расширенных). То есть в полной нотации это будет выглядеть так:

/dev/ide/host0/bus0/target0/lun0/part1 
/dev/ide/host0/bus0/target0/lun0/part2
/dev/ide/host0/bus0/target0/lun0/part3
/dev/ide/host0/bus0/target0/lun0/part5
/dev/ide/host0/bus0/target0/lun0/part6
...

а в краткой - таким образом:

/dev/discs/disc0/part1
/dev/discs/disc0/part2
/dev/discs/disc0/part3
/dev/discs/disc0/part5
/dev/discs/disc0/part6
...

В обоих случаях обращаем внимание на "правильное" написание слова disc... именно так, через букву c.

Интересен вопрос о разделах USB-накопителей (и встроенных носителей цифровых камер). Они поставляются в фабрично отформатированном под vfat виде, однако эта файловая система накладывается на самые разные схемы разбиения. Мне, в частности, приходилось видеть, что форматированию подвергалось все устройство, без разделов (в этом случае обращаться к флэшке из под Linux'а следует - /dev/sda). В иных же случаях файловая система создавалась на 1-м или 4-м первичных разделах - файлы устройств при этом именуются как /dev/sda1 или /dev/sda4, соответственно.

Впрочем, при использовании devfs имя файла устройства, соответствующего флэшке, легко определить методом ползучего эмпиризма. Для этого достаточно просмотреть содержимое каталога /dev до и после подключения USB-драйва: файл, добавившийся во втором случае, и будет искомым именем устройства.

Особенности BSD-разметки

Совершенно иначе (как по существу, так и с точки зрения именования файлов устройств) выглядит BSD-стиль разметки (BSD Label), используемый во FreeBSD, Net- и OpenBSD. Здесь также может быть использована BIOS-таблица, заполнение которой создаст четыре первичных раздела. В терминологии FreeBSD они именуются слайсами (slices - наиболее точным переводом будет "отрезки"), чтобы отличать их от партиций (partitions) BSD-разметки. Слайсы в номенклатуре файлов устройств маркируются добавлением к имени файла диска литеры s и порядкового номера (в отличие от дисков, начиная с единицы), что для Master'а на 1-м IDE-канале будет выглядеть так (табл. 6).

Таблица 6. Номенклатура BSD-слайсов
/dev/ad0s1 1-й слайс
/dev/ad0s1 2-й слайс
/dev/ad0s1 3-й слайс
/dev/ad0s1 4-й слайс

Если одному или нескольким из слайсов будет присвоен идентификатор BSD-системы - 165 в десятичном исчислении (как уже говорилось, он называется 4.2BSD), то в его начальный блок запишется собственно BSD-таблица разделов (BSD Label). В соответствие с ее форматом, каждый слайс с ID 165 абсолютно равноправен и может быть поделен на логические разделы (собственно partitions, в терминологии FreeBSD, именуемые в остальных BSD-системах подразделами - subpartitions).

Для партиций в BSD-таблице предусмотрено восемь (FreeBSD) или шестнадцать (DragonFlyBSD) записей. Соответствующие им разделы номенклатурно маркируются добавлением к имени файла слайса литеры - от a до h (или - до p в случае с DragonFly). То есть таких логических разделов, казалось бы, может быть создано 8 (или, соответственно, 16). Однако практически это не совсем так (вернее, совсем не так).

Начать с того, что одна из записей (третья по счету, маркируемая литерой c) резервируется для описания всего слайса в целом - например, ad0s1c, необходимость чего станет ясной в дальнейшем. Далее, первая запись таблицы, соответствующий которому файл устройства маркируется как ad#s#a, отводится для описания корневого раздела файловой системы. А очевидно, что на конкретной локальной машине корневой раздел может быть только один, вне зависимости от количества дисковых разделов и даже физических дисков.

Наконец, вторая запись (файл устройства - ad#s#b) предназначена исключительно для описания раздела подкачки (swap-раздела), который, во-первых, не может содержать данные, и во-вторых, является единственным на весь диск (ясно, что создавать по своп-разделу в каждом слайсе бессмысленно, хотя при наличии двух физических дисков поделить между ними пространство подкачки - идея вполне здоровая). В итоге на четырех слайсах физического диска средствами FreeBSD может быть создано 22 раздела - 1 корневой, один раздел подкачки и 20 разделов для хранения данных. Максимальное же количество разделов в случае с DragonFlyBSD предлагается подсчитать заинтересованным лицам.

Практически, однако, так никто, насколько я знаю, не делает. Создание слайсов преследует своей целью разместить на диске более чем одну операционку и сохранить возможность обмена данными между ними (теоретически к BSD-разделам можно обращаться из Linux'а, если пересобрать его ядро должным образом; хотя обратная процедура - обращение к Linux-разделу из BSD-системы, - гораздо проще).

Если же весь наличествующий диск планируется отдать на растерзание какой-либо BSD-системе, то проще создать один-единственный слайс на (почти) весь его объем, оставив записи в BIOS-таблице для остальных неиспользованными. Ну а семи (и, тем более, 15) позиций BSD-таблицы обычно достаточно для обособления всех необходимых ветвей файловой системы, таких, как /usr, /tmp, /var и /home. Впрочем, в ряде случаев целесообразно и разнесение разделов по двум слайсам, но - не более.

Разметка диска, использующая записи в BIOS-таблице первого блока, называется разметкой в режиме совместимости. Вне зависимости от того, создается ли один слайс для BSD-системы или несколько отдельных - для каждой операционки, в режиме совместимости в начале диска резервируется пространство в размере 63 блоков (всего около 30 Кбайт), в котором не только сохраняется в неприкосновенности "умолчальный" MBR, но и остается место для записи кода какого-либо стороннего загрузчика. В итоге диск остается доступным для других операционных систем, по крайней мере теоретически.

Однако использование режима совместимости и BIOS-таблицы разделов во FreeBSD не является обязательным. Вполне допустимо записать в MBR, вместо таблицы BIOS, непосредственно BSD-таблицу разделов. В этом случае понятно, что слайсов как таковых не создается, а все дисковое пространство представляет собой как бы единый слайс, и может быть разбито на BSD-партиции по тем же правилам, что и отдельный слайс. И тут становится ясной необходимость резервирования третьего поля BSD-таблицы - именно в ней и описывается весь наш диск, целиком отведенный под BSD-систему.

Такое обращение с диском именуется режимом эксклюзивного использования, или Dangerously Dedicated. Вопреки названию, в нем не таится никакой опасности ни для данных пользователя, ни для его здоровья. А единственная подстерегающая его опасность - это то, что диск в эксклюзивном режиме не будет опознан никакой другой операционной системой, установленной на данном компьютере (обращению к диску по сети он препятствий не составит). Однако это - чисто теоретическое неудобство, потому что ни одна из известных мне операционок все равно не умеет толком работать с BSD-разделами и файловой системой FreeBSD (особенно современной - UFS2). А, скажем, при наличии на другом физическом диске мультизагрузчика GRUB, FreeBSD с "эксклюзивного" диска вполне может быть им загружена.

В документации по FreeBSD встречаются указания, что "эксклюзивные" диски иногда не могут быть загрузочными, вероятно, потому, что BIOS не сможет опознать нестандартные записи в MBR. Однако, видимо, это относится к каким-либо старым версиям BIOS - мне с таким сталкиваться не приходилось, хотя я часто прибегал к эксклюзивному режиму при возможности отдать под FreeBSD целый физический диск.

Тем не менее, в документах проекта FreeBSD всегда подчеркивается, что эксклюзивный режим - в частности, из-за грошовой экономии дискового пространства, - следует использовать лишь в исключительных случаях. Один из резонов к такому использованию - несоответствие "геометрии" диска, видимой из BIOS, и того представления о ней, которое складывается у FreeBSD (подробнее на эту тему можно прочитать в официальном FreeBSD FAQ - http://www.freebsd.org.ua/doc/ru_RU.KOI8-R/books/faq/index.html).

Схема разметки диска в BSD-стиле принята и в других ОС этого семейства, с той разницей, что термин слайс ни в OpenBSD, ни в NetBSD не применяется, и имена файлов разделов именуются - /dev/wd0a, /dev/wd0b и так далее. А в NetBSD, кроме литеры c, предназначенной для описания всего диска, резервируется еще и литера d - файл устройства /dev/wd0d также предназначается для описания первичного раздела целиком.

В ОС BSD-семейства может быть иным и формат таблицы разделов слайса. В частности, в DragonFlyBSD он позволяет разделить слайс не на 8, как во FreeBSD, а на 16 логических разделов.

RAID и LVM

Дисковые разделы любого рода создаются в целях не только размежевания, но и объединения, в результате которого части различных физических носителей предстают перед системой в качестве непрерывного дискового пространства, на котором может быть создана единая файловая система. И целям объединения служат разнообразные технологии программных RAID и LVM.

Понятие RAID родилось из потребности представить набор дисков в виде единого дискового пространства, и первоначально было реализовано посредством специализированных контроллеров с интерфейсами SCSI или ATA (ныне также и Serial ATA). Это - так называемые физические RAID. Конечно, в них за объединение дисков отвечают соответствующие программы, однако они прошиты в микросхемах контроллера, расположенного либо на отдельной карте расширения, либо, как это стало обычным в последнее время, встроенного в материнскую плату.

Объединение дисков и их разделов возможно и при отсутствии специфического "железа" - именно такая реализация называется программным RAID (Soft RAID). Оно требует а) поддержки ядро операционной системы, и б) наличия соответствующего программного инструментария.

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

К массивам без избыточности относятся т.н. линейный режим (linear RAID) и RAID level 0. Первый - это просто последовательное объединение двух и более дисков, так, что они видятся системой как единое устройство. И запись на них осуществляется последовательно - сначала на первый диск, по заполнении его - на второй, и так далее. Диски или разделы, объединяемые в линейный RAID, могут быть произвольного объема, на их количество также не накладывается никаких ограничений.

Создаются линейные массивы исключительно из соображений удобства - если есть потребность в непрерывном дисковом пространстве, превышающем объем наличных дисков или их разделов: они не дают ни повышения быстродействия, ни дополнительной надежности хранения данных. Впрочем, и к снижению надежности они тоже не приводят: при разрушении одного диска или раздела данные со второго остаются доступными точно также, как и при использовании самостоятельных носителей.

Массивы нулевого уровня называются также RAID со strip-режимом - это попарное объединение дисков с распараллеливанием операций чтения/записи). В них каждая порция записываемых данных расслаивается на два равных по размеру логических блока (chunks - этот термин лучше оставить без перевода), один из которых в одну и ту же единицу времени записывается на первый диск или раздел массива, другая - на второй. Что теоретически должно способствовать быстродействию дисковых операций. И - способствует практически, но только при условии, что диски массива разнесены на разные IDE-каналы (о SCSI-дисках у нас тоже речи не будет). В противном случае выигрыша в производительности не только не будет, но весьма вероятно даже ее падение.

Очевидно, что в массив нулевого уровня можно объединить только четное количество дисков или разделов. Кроме того, желательно, чтобы они имели примерно одинаковый объем: в противном случае суммарный объем массива будет кратен размеру самого маленького диска, а все избыточное пространство окажется неиспользуемым.

Использование массивов нулевого уровня не способствует надежности хранения данных - при отказе хотя бы одного диска пропадут они все (тогда как в линейном режиме информация на исправном диске в первом приближении сохранится). Тем не менее, применение параллельного режима может быть оправданным: все же приятно, когда пара-тройка гигабайт копируется пусть не вдвое, но хотя бы в полтора раза быстрее.

Массивы с избыточностью призваны в первую очередь повышать надежность хранения данных. А если при этом еще и возрастает быстродействие дисковых операций - это можно рассматривать как бесплатный бонус. На практике в Linux и BSD используются два уровня избыточных RAID'ов - 1-й и 5-й.

RAID level 1 (называемый также режимом зеркалирования, mirroring) - это простое дублирование записываемых данных на двух дисках или разделах, то есть такой массив обладает 100-процентной избыточностью: при выходе из строя одного диска вся информация сохраняется на диске-дублере (хотя в процессе работы они выступают как равноправные). Очевидно, что, как и в случае с RAID level 0, число дисков или разделов должно быть четным, а их объем - примерно одинаков.

Разумеется, ни о каком росте производительности в массивах первого уровня речи идти не может. Однако на сей предмет level 1 можно комбинировать с level 0 (это называют level 0+1 или, иногда, level 10), когда одна пара дисков в параллельном режиме зеркалируются второй парой. Правда, как нетрудно подсчитать, для этого желательно иметь не только четыре диска, но и соответствующее число отдельных IDE-контроллеров, иначе роста производительности ожидать не придется.

В RAID level 5 данные распределяются по всем составляющим массив дискам (или разделам) и дополняются контрольными суммами. По последним и осуществляется восстановление информации в случае отказа одного из устройств. Минимальное количество дисков (разделов) в таком массиве - три, размер их должен быть примерно равным, и общий объем массива равен произведению объема наименьшего на их число минус единица, так как для хранения контрольных используется часть пространства от каждого диска, в сумме равное объему единичного устройства. Массивы 5-го уровня считаются весьма надежными и теоретически даже обещают некоторый прирост быстродействия.

Создание и использование программных RAID несколько различается в Linux и BSD-системах. И в обоих случаях требуют некоторых не вполне тривиальных действий, которые будут описаны в ближайшей интермедии. В любом случае после создания массива с ними следует обращаться как с обычными дисковыми разделами - создавать на них файловые системы и монтировать их. Впрочем, и об этом разговор будет в той же интермедии.

Программный RAID-массив - некоторым образом лобовой подход к проблеме объединения дисков. Попробуем подойти к ней с другого бока, благо это допускает в виде технологии логических томов (LVM); правда, доступна она только в Linux.

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

Можно создать на диске физический раздел, на нем - новую файловую систему и смонтировать ее к файловой системе корневой в заранее созданный каталог, например, $HOME/newhome. Это проще всего, но не всегда - лучше всего. Ведь в итоге единый пользовательский каталог будет состоять из двух физически различных файловых систем, что накладывает некоторые ограничения на манипулирование данными (например, невозможно создать жесткие ссылки на наборы данных другой файловой системы).

И вообще, это не очень удобно - все время помнить, какие данные находятся на одном физическом диске, какие - на другом. Гораздо проще, если весь пользовательский каталог видится как единое дисковое пространство, путь даже в натуре таковым и не является.

Второй пример, не менее жизненный. Послушавшись совета резонных людей, мы делим диск на многочисленные разделы, как это будет описано в следующей главе, для всех возможных файловых систем - под каталоги /usr, /usr/local, /opt, /var, /tmp, /home. И очень быстро убеждаемся, что под /usr/local отвели слишком много места - весь нужный нам софт по умолчанию желает собираться в каталоге /opt (с объемом которого мы явно пожадничали). А каталог /usr, вследствие изобилия Иксовых приложений, напротив, заполняется через чур уж стремительно, что отнюдь не есть хорошо: производительность дисковых операций в любом Unix'е стремительно падает по достижении определенного предела заполненности файловой системы. Ну а каталог /tmp просто бездействует - роль хранителя временных файлов, как оказалось, с успехом исполняет файловая система в оперативной памяти - tmpfs. И что, спрашивается, делать? Вариант тотальной архивации и переразбиения дисков - просьба не предлагать.

Обеих ситуаций можно избежать, если предугадать такие коллизии заранее. И еще на стадии разбиения диска прибегнуть к технологии LVM (Logical Volume Manager), то есть управления логическими томами.

Вводное замечание, касаемое терминологии. Пользователи DOS/Windows знают, что логическими томами (logical volumes) называются те части, на которые бьется расширенный (extended) раздел DOS. Однако в случае LVM в понятие логического тома вкладывается, как станет ясно очень скоро, совершенно иной смысл. И потому в этой книге я по возможности именую части расширенного DOS-раздела незамысловато - логическими разделами (впрочем, примерно такая терминология принята в Linux-программах разбиения диска), а звание логического тома сохраняется только за элементом структуры LVM.

Теперь можно перейти к сути дела. Основа технологии LVM - в выделении двух уровней организации дискового пространства, физического и логического. Единица физической организации - физический том (Physical Volume). Это - не что иное, как самый обычный дисковый раздел с определенным идентификатором типа файловой системы - 8e (Linux LVM), который присваивается разделу при его создании, например, программой fdisk. Физический том делится на физические же блоки (physical extents) - кванты дискового пространства, на которые может изменяться размер логических ресурсов (своего рода аналог обычного физического блока винчестера).

Единицей организации логической в LVM выступает группа томов (Volume Group). Она сливает воедино физические тома так, что для ОС они выглядят как единый носитель, и, следовательно, может представляться как нечто вроде логического аналога винчестера. Как и винчестер, группа томов может делиться на разделы (или, напротив, представлять собой единый раздел). Один такой раздел и есть логический том, на котором создаются обычные файловые системы и к которому непосредственно обращается пользователь, например, при монтировании. Он образован последовательностью логических блоков (logical extents), которые можно сопоставить с логическими блоками обычного раздела, размечаемыми при создании файловой системы. А уж эти логические extent'ы (во избежание путаницы оставляю этот термин без перевода) по определенным правилам связываются с extent'ами физическими.

В LVM-HOWTO взаимосвязь элементов LVM иллюстрируется следующим образом:

    hda1   hdc1      (PV:s on partitions or whole disks)
          /
         /
       diskvg        (VG)
      /  |  
     /   |   
  usrlv rootlv varlv (LV:s)
   |      |     |
ext2  reiserfs  xfs (filesystems)

Взаимосвязь физических и логических extent'ов обозначается термином mapping. Причем возможны два варианта такой взаимосвязи - линейный (linear mapping) и "чередующийся" (striped mapping). В первом случае непрерывной последовательности физических extent'ов просто ставится в соответствие столь же непрерывная последовательность extent'ов логических. Во втором же - непрерывная последовательность логических extent'ов соотнесена с физическими extent'ами, чередующимися между физическими носителями:

   .+-- Volume Group --------------------------------+
   |                                                |
   |    +----------------------------------------+  |
   | PV | PE |  PE | PE | PE | PE | PE | PE | PE |  |
   |    +----------------------------------------+  |
   |      .          .          .        .          |
   |      .          .          .        .          |
   |    +----------------------------------------+  |
   | LV | LE |  LE | LE | LE | LE | LE | LE | LE |  |
   |    +----------------------------------------+  |
   |            .          .        .         .     |
   |            .          .        .         .     |
   |    +----------------------------------------+  |
   | PV | PE |  PE | PE | PE | PE | PE | PE | PE |  |
   |    +----------------------------------------+  |
   |                                                |
   +------------------------------------------------+

Эта схема подобна той, что осуществляется в описанных выше программных RAID-массивах нулевого (strip) уровня и преследует ту же цель - повышение производительности дисковых операций. Правда, последнее достижимо только в том случае, если физические тома, на которых созданы чередующиеся физические extent'ы, расположены не просто на разных дисках, но и на разных IDE-каналах; иначе, напротив, потери производительности могут быть просто катастрофическими.

Из сказанного ясно, что технология LVM наиболее эффективна ( и эффектна) в случае, если в машине имеется более одного физического диска. Однако и в однодисковой системе ее можно использовать с большим успехов (в том числе и в расчете на обогащение вторым накопителем).

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

Общие черты файловых систем POSIX-семейства

Итак, файловые системы обычно размещаются на отдельных дисковых разделах или их объединениях. Соотношение между файловыми системами не вполне однозначно. На одном разделе может быть размещена одна файловая система. Однако последняя, в общем случае, может располагаться более чем на одном разделе. Такие технологии, как LVM (Logical Volumes Managers) или программный RAID, позволяют объединить несколько дисковых разделов в единое логическое устройство, которое целиком занимается одной файловой системой. Впрочем, после такого объединения (конкатенации) прежде самостоятельные разделы видятся системой точно так же, как и обычные разделы или слайсы диска.

Физически все файловые системы в ОС, соответствующих стандарту POSIX, организованы сходным образом. И в основе их лежит разделение на три пространственно разобщенные области - суперблок, область метаданных и блоки данных.

Суперблок - это первый (после загрузочного) блок раздела, занятого данной файловой системой. Он содержит наиболее общую информацию о ней - размер логического блока (который следует отличать от физического дискового блока), их суммарное количество, число блоков данных, количество свободных и занятых блоков. Кроме того, в нем записывается и информация, специфичная для определенных файловых систем.

Содержимое области метаданных составляет таблица inodes - это данные о данных файловой системы. Для каждого файла она содержит: его уникальный идентификатор, по которому он находится системой, число ссылок на него (фигурально говоря, количество имен файла), размер, атрибуты принадлежности, доступа, времени, и еще некоторые, о чем говорилось в главе 8-й.

Адреса блоков данных файла, то есть собственно физического расположения его контента на диске, также описываются в таблице inodes. Ну а сами блоки данных, как легко догадаться, и составляют наполнение одноименной области.

Описанным способом была организована первая файловая система первозданного Unix, получившая позднее название s5fs (то есть файловая система System V). Как уже говорилось в историческом обзоре (см. главу 3), в самой ее приоде были заложены существенные ограничения, не способствовавшие ни надежности, ни быстродействию, ни эффективности использования дискового пространства. И потому разработчики всех более поздних файловых систем POSIX-совместимых ОС, приняв за основу организацию s5fs, вносили в нее те или иные усовершенствования, направленные на исправление указанных недостатков.

Борьба за повышение быстродействия файловых операций осуществлялась дроблением файловой системы на более или менее независимые части, получившие название групп цилиндров (в ОС BSD-семейства), групп блоков (в файловой системе Linux), вплоть до обособления allocation groups в файловой системе XFS, где они представляют фактически самостоятельные файловые подсистемы. В результате этого появилась возможность размещения логически связанной информации в физически смежных областях диска, что минимизировало перемещение дисковых головок, способствуя тем самым скорости доступа к данным.

Расчленение файловой системы одновременно способствовало и росту их надежности. Так как давало возможность в разных ее частях дублировать критически важную информацию - а именно, суперблок, утрата которого (вследствие, например, физического повреждения дисковой поверхности) ранее влекла за собой невозможность доступа к данным вообще.

Экономия в использовании дискового пространства достигалась прямо противоположным приемом - так называемой внутренней фрагментацией, то есть разделением на части логического блока файловой системы. И теперь маленькие файлы могли занимать уже не блок целиком, а только его часть. Венцом творения в этой области явилась файловая система ReiserFS, в которой даже данные маленьких файлов удается целиком вписать в область ее метаданных.

Еще одна общая особенность всех файловых систем Unix-подобных операционок - это кэширование дисковых операций, как чтения, так и записи. Строго говоря, само по себе кэширование к устройству файловой системы имеет не много отношения, поддерживаясь на уровне ядра, а включаясь (или отключаясь) при монтировании. Однако оно очень важно с точки зрения восприятия файловых операций пользователем, и потому здесь уместно сказать о нем несколько слов.

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

Существует два режима кэширования файловых операций: частично синхронный и чисто асинхронный. При первом изменения в метаданных записываются на диск немедленно, а отложенная запись применяется только в отношении измененных данных. При чисто асинхронном режиме кэшируются как данные, так и метаданные.

Как уже было отмечено, режим кэширования определяется при монтировании файловых систем (как - об этом пойдет речь в следующей главе). И в принципе любая из файловых систем Linux или BSD может быть смонтирована как в том, так и в другом режиме. Однако файловые системы BSD традиционно используются в частично синхронном режиме, а все файловые системы, поддерживаемые в Linux - в асинхронном.

Кэширование дает просто потрясающий эффект с точки зрения быстродействия файловых операций, особенно выраженный при асинхронном режиме. Расплатой за что становится возможное нарушение целостности файловых систем при сбоях - аппаратных, или просто при некорректном завершении работы. Ведь в этом случае буферизованные изменения данных и что хуже, метаданных, теряются.

В BSD-системах в качестве метода борьбы с этими явлениями была разработка матода SoftUpdates (о котором будет сказано чуть ниже). В Linux'е же основным направлением в повышении надежности файловых операций явилось развитие так называемых журналируемых файловых систем. Журнал -- это часть файловой системы, отведенная под протоколирование выполненных и предстоящих файловых операций, а также под сохранение данных о текущем (на некие моменты времени) ее состоянии. Что, в случае аварийного завершения работы, нарушившего целостность данных и (в первую очередь) метаданных, дает возможность откатиться назад, в последнее "нормальное" состояние.

Основные типы файловых систем POSIX-мира

Таковы общие особенности файловых систем Unix и его производных. Теперь охарактеризуем наиболее используемые в свободных ОС POSIX-семейства их разновидности.

Файловая система BSD-семейства

Для файловой системы BSD-систем, начиная с 4.2BSD, используется общее родовое наименование - FFS (Fast File System). Название это отражает их большее быстродействие относительно первознанной s5fs, хотя среди современных файловых систем они - в числе самых медленных. Реализация UFS для FreeBSD и DragonFlyBSD носит название UFS (Unix File System). Во FreeBSD 5-й ветке используется усовершенствованная, 64-разрядная, разновидность последней - UFS2. Она с некоторых пор поддерживается также в NetBSD и DragonFly, хотя и не является в них используемой по умолчанию. Фактически FFS и разновидности UFS - единственные нативные файловые системы для ОС BSD-семейства, хотя на уровне обмена данными в них можно использовать файловые системы FAT-семейства и, с оговорками, некоторые типы файловых систем Linux.

Как уже говорилось ранее, дисковый раздел, на котором создается файловая системы, - это, говоря метафорически, группа смежных цилиндров, разбитых на физические блоки по 512 байт. Однако специфика файловых систем BSD-клана заключается в том, что при их создании раздел делится еще и на части фиксированного объема (зависящего от объема раздела). Это так называемые группы цилиндров, каждая из которых имеет включает три самостоятельные части:

  • суперблок, идентичный по содержанию для всех групп;
  • блок группы цилиндров, оную описывающий; одной из важнейших его
  • частей является индексная таблица (или таблица inodes);
  • область блоков данных.

Рассмотрение их устройства целесообразно начать с конца списка, то есть с области данных.

Область данных (она занимает подавляющий объем пространства каждой группы цилиндров) образована блоками файловой системы. Подобно физическому блоку, о котором речь была ранее, блок файловой системы (именуемый также блоком логическим) представляет собой квант информации, доступный за одну операцию чтения/записи, но уже не дисковой головки, а операционной системы. Очевидно, что логический блок не может быть меньше блока физического (то есть 512 байт), и размер его обязательно кратен целому числу последних.

Понятие логического блока введено для повышения производительности дисковых операций. Не требует доказательства утверждение, что скорость обмена данными квантами по 1 Кбайт будет выше, чем 512-байтными, 2-килобайтными - еще быстрее, и так далее. И потому с точки зрения быстродействия файловых операций выгоден максимальный размер логического блока файловой системы.

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

Ясно, что размер фрагмента все равно не может быть меньше физического блока. При этом UFS накладывает на него и встречное ограничение - минимальный размер фрагмента определяется в 1/8 логического блока. Другие же возможные значения - 1/4 и 1/2 блока файловой системы (очевидно, что выделение фрагмента в размере блока равносильно отказу от фрагментации блока вообще, хотя это, как будто бы, не запрещено).

Каким образом определяется принадлежность блока данных тому или иному файлу? К помощью индексной таблицы, именуемой также таблицей индексных дескрипторов или таблицей inodes. Она образована некоторым (конечным) количеством записей фиксированной длины (128 байт в UFS, 256 - в UFS2), каждая из которых однозначно соответствует одному файлу, как реально существующему, так и только могущему быть созданным.

Такая запись индексной таблицы носит название inode. Каждый из них содержит так называемые метаданные файла. Для реально существующего файла они включают в себя идентификатор, тип файла и еще кое-какие атрибуты, рассмотренные ранее. Для файлов несуществующих свободные записи в таблице inodes просто резервируются. А поскольку количество этих записей - величина конечная, именно объем индексной таблицы и определяет, сколько файлов реально может быть создано в данной файловой системе. Исчерпание свободных записей в ней приводит к тому, что, вне зависимости от объема свободного дискового пространства, ни одного нового файла создать не удастся.

Таблицы inodes содержатся в блоке группы цилиндров, наряду с картами свободных/занятых inodes и карты свободных/занятых блоков данных). Это имеет целью размещение inodes и относящихся к ним блоков данных максимально близко друг к другу, что, кроме повышения производительности (за счет минимизации перемещений головок), влечет за собой и сведение к минимуму той самой внешней фрагментации данных, о которой, как факторе несущественном, упоминалось выше.

Однако сведений об объеме индексной таблицы в блоке группы цилиндров не обнаруживается. Ибо место их размещения - тот самый суперблок, который идет первым в любом разделе (вообще-то первым будет загрузочный блок, но реально он занят только в загрузочном же разделе - во всех остальных для него просто зарезервировано место). А также дублируется в каждой группе цилиндров - чем обеспечивается устойчивость к механическим повреждениям диска. Кроме этого, в суперблоке же записывается размер блока файловой системы и их суммарное количество, число блоков данных, размер блокового фрагмента и их число в блоке, число блоков, реально занятых файлами, объем партиции, перманентно резервируемый как свободный, и еще множество характеристик файловой системы.

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

Исправлению обоих недостатков служит так называемый механизм SoftUpdates (оставим этот термин без перевода - варианты оного типа "мягких обновлений" не только не блещут литературным изяществом, но и сути дела не проясняют). Он детально описан в специальной статье Макказика и Ганджера, смысла пересказывать которую я не вижу (благо она имеется в русском переводе - http://www.osp.ru/os/1999/07-08/13.htm). В двух же словах суть этого механизма - в сведении к минимуму синхронных операций записи без явно асинхронного манипулирования метаданными, с одной стороны, но и без предварительного журналирования метаданных (как в файловых системах типа ReiserFS или XFS) - с другой.

Реализуется это за счет так называемых зависимостей обновления. Что такое эти зависимости - интуитивно ясно из примера создания нового (для простоты - пустого) файла. Для этого требуется:

  • запись в таблице inodes, с заполнением полей типа файла, его идентификатора, счетчика ссылок, ну и прочих там - прав доступа в соответствие с умолчальной маской, и так далее;
  • изменение карты свободных/занятых inodes в блоке группы цилиндров (соответствующий новому файлу inode должен быть помечен в ней битом занятости);
  • внесение записи вида "идентификатор - имя_файла" в структуру каталога, в котором новый файл создается, что обеспечивает ту самую единственную ссылку в соответствующем поле inode файла.

С точки зрения целостности файловой системы, эти операции должны быть выполнены именно в указанной последовательности. То есть наличие в каталоге имени файла с идентификатором незаполненного (еще не созданного или уже уничтоженного) inode - явный непорядок: именно для исправления такого рода безобразий и запускается программа проверки диска после аварийного завершения сеанса.

Выполнять связанные зависимостями операции обновления в синхронном режиме - долго (каждая потребует своего обращения к диску), в чисто асинхронном - нет гарантии сохранения последовательности (обновления в кэше могут быть записаны тогда, когда бог на душу положит). Так вот, механизм SoftUpdates обеспечивает, с одной стороны, контроль за последовательностью выполнения зависимых обновлений (что способствует целостности состояния файловой системы), с другой - группирует их в единую атомарную операцию синхронного обращения к диску, за счет сокращения числа коих и растет производительность. В этом и состоит объяснение парадокса SoftUpdates - неожиданного увеличения и надежности, и быстродействия.

Файловые системы Linux

В Linux длительное время также имелась только одна нативная файловая система, носящая имя Ext2fs. О ней написано немало, поэтому буду краток. Название ее расшифровывается как "вторая расширенная файловая система"; "расширенная" она - по сравнению с файловой системой ОС Minix, послужившей прототипом Linux (и до сих пор используемой на отформатированных в этой ОС дискетах), "вторая" - потому что ранние версии Linux базировались на Extfs с более ограниченными возможностями.

По способу организации хранения данных она - типичная представительница файловых систем Unix. Отличительная ее особенность - дробление дискового раздела на группы блоков и наличие нескольких копий суперблока, что повышает надежность хранения данных. Кроме того, для нее характерен очень эффективный механизм кэширования дисковых операций, что обеспечивает замечательное их быстродействие - едва ли не рекордное среди всех известных файловых систем. Оборотная сторона чего, однако, - относительно слабая устойчивость при аварийном завершении работы (вследствие мертвого зависания или отказа питания), поскольку отложенность записи изменений файлов делает весьма высокой вероятность нарушения связи между их inodes и блоками данных.

Конечно, времена, когда некорректный останов Linux-машины грозил полным разрушением файловой системы, остались в далеком прошлом. Однако в любом случае останов системы без штатного размонтирования файловых систем приводит к тому, что в них не устанавливается упоминавшийся ранее неоднократно "бит чистого размонтирования". А без этого утилиты обслуживания диска (такие, как программа проверки fsck) при перезагрузке не воспринимают их как целостные и начинают проверку, которая при современных объемах дисков может занять немалое время.

Проблема нарушения целостности файловой системы при некорректном завершении работы в большей или меньшей мере характерна для всех ОС семейства Unix. И потому с давних пор в них разрабатываются т.н. журналируемые файловые системы. Журнал -- это нечто вроде log-файла дисковых операций, в котором фиксируются не выполненные, а только предстоящие манипуляции с файлами, вследствие чего оказывается возможным самовосстановление целостности файловой системы после сбоя.

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

Более того, в большинстве журналируемых файловых систем фиксируются грядущие операции только над метаданными изменяемых файлов. Обычно этого достаточно для сохранения целостности файловой системы и, уж во всяком случае, предотвращения долговременных их проверок, однако не предотвращает потери данных в аварийных ситуациях. В некоторых из файловых систем возможно распространение журналирования и на область данных файла. Однако, как всегда, повышение надежности за счет этого оплачивается снижением быстродействия.

Текущие версии ядра Linux поддерживают в качестве нативных четыре журналируемые файловые системы: ReiserFS и Ext3fs, специфичные для этой ОС, XFS и JFS - результаты портирования в Linux файловых систем, разработанных первоначально для рабочих станций под ОС Irix (SGI) и AIX (IBM), соответственно. Правда, широкое признание получили только три первых, так что о JFS я говорить не буду.

Файловая система ReiserFS оказалась для Linux исторически первой из журналируемых - она поддерживается каноническим ядром c http://www.kernel.org, начиная с первых версий ветви 2.4.x. И была единственной, разработанной "с нуля" специально для этой ОС Хансом Райзером и его фирмой Namesys(http://www.namesys.com). В ReiserFS осуществляется журналирование только операций над метаданными файлов. Что, при определенном снижении надежности, обеспечивает высокую производительность: на большинстве типичных пользовательских задач она лишь незначительно уступает Ext2fs. А на такой, достаточно обычной, операции, как копировании большого количества мелких файлов, существенно ее опережает.

Кроме этого, ReiserFS обладает уникальной (и по умолчанию задействованной) возможностью оптимизации дискового пространства, занимаемого мелкими, менее одного блока, файлами (а следует помнить, что в любой Unix-системе такие файлы присутствуют в изобилии): они целиком хранятся в своих inode, без выделения блоков в области данных - вместе с экономией места это способствует и росту производительности, так как и данные, и метаданные (в терминах ReiserFS - stat-data) файла хранятся в непосредственной близости и могут быть считаны одной операцией ввода/вывода.

Вторая особенность ReiserFS - то, что т.н. хвосты файлов, то есть их конечные части, меньшие по размеру, чем один блок, могут быть подвергнуты упаковке. Этот режим (tailing) также включается по умолчанию при создании ReiserFS, обеспечивая около 5% экономии дискового пространства. Что, правда, несколько снижает быстродействие, и потому режим тайлинга можно отменить при монтировании файловой системы. Однако упаковка хвостов автоматически восстанавливается на файловой системе, в которую было инсталлировано новое ядро - что по некоторым причинам требует внимательного отношения.

ReiserFS не совместима с Ext2fs на уровне утилит обслуживания файловой системы. Однако соответствующий инструментарий, объединенный в пакет reiserfsprogs, уже давно включается в штатный комплект современных дистрибутивов (или, в крайнем случае, может быть получен с сайта Namesys.

Более серьезная проблема с совместимостью - в том, что распространенные загрузчики Linux (и Lilo, и GRUB - хотя и по разным причинам) иногда не способны загрузить ядро Linux с раздела ReiserFS, оптимизированного в режиме тайлинга. А поскольку, будучи отключен, этот режим обладает свойством самовосстановления, пользователь может столкнуться с тем, что после пересборки ядра система просто откажется загружаться. Так что ReiserFS не рекомендуется к употреблению на загрузочном разделе.

В отличие от ReiserFS, Ext3fs - не более чем журналируемая надстройка над классической Ext2fs, разработанная Стивеном Твиди в компании Red Hat и поддерживаемая ядром Linux, начиная с версии 2.4.16. Как следствие такого происхождения, она сохраняет со своей прародительницей полную совместимость, в том числе и на уровне утилит обслуживания (начиная с версии 1.21 объединяющего их пакета e2fsprogs). И переход от Ext2fs к Ext3fs может быть осуществлен простым добавлением файла журнала к первой, не только без переформатирования раздела, но даже и без рестарта машины.

Из этого вытекает первое преимущество Ext3fs, особенно весомое в случае большого парка компьютеров. Второе же - чуть ли не максимальная надежность: Ext3fs является единственной системой из рассматриваемых, в которой возможно журналирование операций не только с метаданными, но и с данными файлов. Ибо в Ext3fs предусмотрено три режима работы - полное журналирование (full data journaling), журналирование с обратной записью (writeback), а также задействуемое по умолчанию последовательное журналирование (ordered).

Режим полного журналирования, как легко догадаться из названия, распространяется и на метаданные, и на данные файлов. Все их изменения сначала пишутся в файл журнала и только после этого фиксируются на диске. В случае аварийного отказа журнал можно повторно перечитать, приведя данные и метаданные в непротиворечивое состояние. Этот механизм практически гарантирует от потерь данных, однако является наиболее медленным.

В режиме отложенной записи, напротив, в файл журнала записываются только изменения метаданных файлов, подобно всем рассмотренным ниже файловым системам. То есть никакой гарантии сохранности данных он не предоставляет, однако теоретически обеспечивает наибольшее (в рамках Ext3fs) быстродействие.

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

Файловая система XFS, в отличие от молодых ReiserFS и ext3fs, развивается фирмой SGI для ее собственного варианта Unix на протяжении более десятка лет - впервые она появилась в версии Irix 5.3, вышедшей в 1994 г. Но в Linux она была портирована лишь недавно (текущая ее версия свободно доступна с SGI's XFS page - http://oss.sgi.com/projects/xfs), и штатно поддерживается ядром, лишь начиная с его ветки 2.6.X.

XFS - единственная 64-разрядная файловая система из используемых в Linux. Однако уникальность ее - не только в этом. Особенностями XFS являются:

  • механизм allocation group, то есть деление единого дискового раздела на несколько равных областей, имеющих собственные списки inodes и свободных блоков, для распараллеливания дисковых операций; в сущности, это - почти самостоятельные файловые субсистемы; логическое журналирование только изменений метаданных, но - с частым сбросом их на диск для минимизации возможных потерь при сбоях;
  • механизм delayed allocation - ассигнование дискового пространства при записи файлов не во время журналирования, а при фактическом сбросе их на диск, что, вместе с повышением производительности, предотвращает фрагментацию дискового раздела;
  • списки контроля доступа (ACL, Access Control List) и расширенные атрибуты файлов (extended attributes), рассмотрение которых далеко выходит за рамки нынешней темы.

В результате XFS предстает как очень сбаллансированная файловая система, ориентированная на размещение в очень больших дисковых разделах для рабботы с очень большими файлами.

И, наконец, эпоним журналируемых файловых систем, JFS (разработка IBM для собственной версии Unix, AIX), уже долгое время поддерживается ядром Linux в качестве нативной. Однако по ряду причин широкого распространения здесь она не получила. Так что, за отсутствием собственного опыта, от ее характеристики воздержусь.

На уровне обмена данными и Linux, и BSD поддерживают множество файловых систем, некоторые - только в режиме чтения, другие же - и записи тоже. Важнейшими для пользователя являются файловые системы CD- и DVD-дисков (ISO9660 и UDF, соответственно) и вариации на тему FAT, а также NTFS (последняя - практически только в режиме чтения).

Кроме того, Linux и BSD теоретически поддерживают файловые системы друг друга. Теоретически - потому, что прочитать из Linux раздел с UFS - задача нетривиальная (а раздел с UFS2 - пока невозможная), запись же на него, как пишут в документации, - дело рискованное для сохранности данных. Во FreeBSD и DragonFlyBSD же поддерживается чтение и запись для файловых систем Ext2fs и Ext3fs без особых сложностей (по крайней мере, я с проблемами здесь не сталкивался). Ведутся работы по восприятию ReiserFS и XFS (пока - только в режиме чтения), существуют и патчи для доступа к JFS.

Все упомянутые выше файловые системы могут располагаться не только на реальных блочных устройствах (дисках и дисковых разделах), но и на виртуальных дисках - т.н. RAM-дисках. Впрочем, кроме того, что они располагаются в оперативной памяти (занимая некий фиксированный ее участок), в остальном они ведут себя точно так же, как и обычные дисковые разделы. Тем не менее, они знаменуют собой плавный переход к явлению, именуемому -

Виртуальные файловые системы

До сих пор речь шла о файловых системах, размещаемых на блочных устройствах (block devices based) или, иначе говоря, "реальных". Однако POSIX-совместимые операционки поддерживают еще и несколько типов виртуальных файловых систем. Они не занимают места на диске (или - почти не занимают), располагаясь в оперативной памяти, и служат для специальных целей.

Исторически первой из таких виртуальных файловых систем была файловая система процессов - procfs. Как можно догадаться из названия, она представляет протекающие в системе процессы в виде файлов каталога /proc, откуда и получают информацию о процессах команды типа ps и top. Однако и пользователь может извлечь оттуда немало полезной для себя информации.

В каталоге /proc каждому процессу соответствует подкаталог, именем которого является идентификатор процесса (просто номер в порядке запуска). Внутри такого подкаталога обнаруживается набор файлов (разный, в зависимости от ОС). Содержимое некоторых из них можно посмотреть обычным способом и обнаружить там информацию об имени запустившей процесс команды, используемых ею адресах памяти и так далее.

Множество важной информации содержится в файлах корня /proc. Из них обычными командами просмотра можно извлечь сведения о процессоре (/proc/cpuinfo), текущей конфигурации ядра системы (/proc/config.gz), загруженных его модулях (/proc/modules), устройстах, подсоединенных к шине PCI (/proc/pci) - в частности, иногда только тут можно узнать подробности о своей сетевой карте и внутреннем модеме, необходимые для правильной их настройки.

Следующей виртуальной файловой системой является файловая система устройств - devfs. Она по умолчанию задействована во FreeBSD 5-й ветки и во многих (хотя и далеко не всех) современных дистрибутивах Linux. Чтобы понять ее назначение, нужно вспомнить, как происходило обращение с файлами устройств ранее.

А происходило оно так. Некий набор файлов устройств генерировался при начальной установке системы. Каждый файл устройства характеризовался своим старшим (major) и младшим (minor) номерами. Первый определял класс устройств, например, диски, терминалы и псевдотерминалы, параллельные или последовательные порты, и так далее. Младший же номер был идентификатором конкретного устройства в данном классе. Очевидно, что сочетание старшего и младшего номеров должно быть уникальным.

Файлы устройств генерировались в некотором соответствии с реальностью, но по принципу явной избыточности. Например, при наличии IDE-контроллера, поддерживающего до 4-х устройств, создавались файлы для всех теоретически подключаемых к нему дисков, даже если в наличии имелся только один. То же и с псевдотерминалами - файлов вида pty* в каталоге /dev можно было обнаружить немерянно (и понятно, почему - ведь каждый запущенный в X-сессии экземпляр эмулятора терминала вроде xtrem требовал своего такого устройства). В результате каталог /dev приобретал объем просто необозримый.

И тем не менее, подчас наличных файлов оказывалось недостаточно для представления всех нужных устройств. И тогда пользователю приходилось их создавать самостоятельно. Файлы для большинства распространенных устройств можно было создать с помощью специально предназначенного сценария /dev/MAKEDEV. Однако иногда он оказывался бессильным (особенно для новых устройств, сценарием еще неучтенных), и приходилось прибегать к чисто ручному созданию файлов устройств командой mknod. Что было не так уж и трудно само по себе, но требовало знания старшего номера создаваемого устройства (младший при этом вычислялся легко).

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

Более того, devfs сделала очень легким "горячее" подключение устройств (типа карт PCMCIA, USB-накопителей, цифровых камер и сканеров с этим интерфейсом). Достаточно воткнуть USB-драйв в соответствующий разъем - и в каталоге /dev можно будут наблюдать появление соответствующего ему файла.

В настоящее время в Linux файловая система устройств постепенно заменяется системой поддержки динамического именования устройств - udev, однако использование ее не стало еще общепризнанным.

В отличие от devfs, udev - не новая поддерживаемая ядром файловая система, пусть и виртуальная, а обычная пользовательская программа (входящая в одноименный пакет). Более того, при ее использовании необходимость в поддержке devfs отпадает вообще.

Правда, для своего функционирования udev нуждается в еще одной виртуальной файловой системе - sysfs, но ее поддержка в ядрах серии 3.6.X осуществляется автоматически (а сама эта файловая система монтируется по умолчанию в каталог /sys). Основываясь на информации из которой, udev и присваивает имена всяческим устройствам (в том числе и при горячем их подключении).

Как уже говорилось, любой POSIX-системе имена файлов конкретных устройств более или менее безразличны, так как оперирует она не с ними, а с их идентификаторами. Ранее в качестве таковых выступали старший и младший номера устройства, определяющие их класс и конкретный экземпляр его. В udev же в ход пошли непосредственные идентификаторы устройств - сериальный номер винчестера, его положение на канале IDE-шины, и так далее, сочетание которых для каждого диска (раздела, и так далее) оказывается уникальным. Программа udev извлекает эти сведения из файловой системы sysfs и, руководствуясь определенными правилами, ставит им в соответствие "человеческие" имена (вроде /dev/hda и так далее).

Во FreeBSD и многих дистрибутивах Linux используется также файловая система в оперативной памяти, именуемая mfs в первом случае и tmpfs - во втором. Реализованы они по разному, но с точки зрения пользователя выглядят почти одинаково - как дисковые разделы, смонтированные в некоторые каталоги. И на самом деле они заменяют собой блочные устройства там, где требуется быстрая, но не обязательно долговременная, запись. То есть их целесообразно использовать для всякого рода промежуточных каталогов при архивации/разархивации, пакетной конвертации графических файлов, а также компиляции программ.

В отличие от "нормальных" файловых систем для хранения данных, mfs и tmpfs не нуждаются в создании: для ее использования достаточно факта поддержки ядром (непосредственно или в виде модуля) и монтирования в какой-либо каталог. Обычно таким каталогом выступает /tmp, содержимое которого не должно сохраняться после рестарта системы. В BSD-системах в некоторых случаях целесообразно монтирование mfs в каталог /usr/obj, предназначенный для промежуточных продуктов компиляции при сборке ядра и базовых компонентов. А в Linux одно из штатных мест монтирования tmpfs - каталог /dev/sh. В Source Based дистрибутивах имеет смысл размещать на tmpfs также каталоги для продуктов промежуточной сборки из портообразных систем.

И в заключение нужно сказать несколько слов о своппинге и разделе для него. Строго говоря, свопиинг не имеет отношения к файловым системам, однако лучшего места для этой темы я придумать не смог.

Итак, ранее неоднократно упоминалось о разделе, предназначенном для своппинга - то есть области диска, куда может выгружаться часть содержимого оперативной памяти. В Linux и BSD механизм свопирования несколько различен. В первой системе освобождение оперативной памяти происходит при ее переполнении. В системах же BSD-семейства на своп-раздел помещаются фрагменты ОЗУ, не использовавшиеся в течении определенного времени.

С точки зрения программ (и их пользователя) физическая память и раздел своппинга представляют собой единое пространство виртуальной памяти. Что особенно четко выражено в BSD, где ОЗУ может рассматриваться как своего рода кэш по отношению к виртуальной памяти.

Для того, чтобы использовать область подкачки, нужно для создать соответствующий раздел (первичный или логический - без разницы, главное - с соответствующим идентификатором, каковой для Linux swap будет 82). В BSD-системах под своппинг отводится подраздел (subpartition) внутри слайса.

Рекомендованный размер раздела подкачки во всех системах - удвоенный объем оперативной памяти. Что нынче может показаться излишеством: в машинах типичных современных конфигураций (с ОЗУ минимум 256, а то и 512 Мбайт) под Linux раздел подкачки в ходе обычной пользовательской работы практически не задействуется, а в BSD-системах используется лишь ничтожная его доля.

Тем не менее, большие объемы swap-раздела целесообразны при активном использовании временных систем в оперативной памяти - tmpfs и mfs. В этом случае при заполнении ОЗУ эти файловые системы автоматически могут быть расширены за счет раздела подкачки. Казалось бы, это - смена шила на мыло: какой смысл подменять disk based файловую систему на систему, частично размещаемую на своп-разделе (то есть также на диске)? Однако некоторый резон к тому есть: ибо в область своппинга попадают наименее используемые части ОЗУ, так что некоторый выигрыш в быстродействии операций с временными файлами сохраняется. Правда, не стоит обольщаться - выигрыш этот не очень велик, и в наиболее благоприятных условиях не превысит 10%.

Кроме выделения раздела под своппинг, требуется явным образом определить его в этом качестве и активизировать специальными командами. Поддержка виртуальной памяти - одна из жестких функций ядра и Linux, и BSD-систем. Единственное, в чем оно еще нуждается - это в указании дискового раздела в файле /etc/fstab. Впрочем, это будет темой ближайшей интермедии.

[ опубликовано 30/08/2005 ]

Алексей Федорчук - Глава 9. Физика файловых систем   Версия для печати