Анатомия виртуального коммутатора файловых систем Linux

Абстракции и общие концепции

Операционная система Linux®— само воплощение гибкости и расширяемости. Возьмём, к примеру, виртуальный коммутатор файловых систем (virtual file system switch, VFS). Он позволяет создавать файловые системы на различных устройствах, — на традиционных дисках, USB флэш-накопителях, в памяти, на других устройствах хранения. Можно даже встроить файловую систему в контекст другой файловой системы. Давайте узнаем, что же делает VFS столь мощным инструментом, и рассмотрим его основные интерфейсы и процессы.

M. Тим Джонс, инженер-консультант, Emulex Corp.

М. Тим ДжонсМ. Тим Джонс - архитектор встроенного ПО и, кроме того, автор книг Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming (выдержавшей на данный момент второе издание), AI Application Programming (второе издание) и BSD Sockets Programming from a Multilanguage Perspective. Он имеет обширный опыт разработки ПО в самых разных предметных областях - от ядер специальных ОС для геосинхронных космических аппаратов до архитектур встраиваемых систем и сетевых протоколов. Тим - инженер-консультант Emulex Corp., Лонгмонт, Колорадо.



17.02.2011

Гибкость и расширяемость поддержки файловых систем в Linux является прямым следствием наличия абстрагированного набора интерфейсов. В основе этого набора интерфейсов лежит виртуальный коммутатор файловых систем (virtual file system switch, VFS).

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

VFs или VFS?

VFS расшифровывается либо как виртуальная файловая система (virtual file system), либо как виртуальный коммутатор файловых систем (virtual file system switch). Второе определение точнее, поскольку этот уровень фактически коммутирует (переключает) запросы между несколькими файловыми системами. Дополнительную путаницу вносит файловая система /proc, которую также часто называют виртуальной файловой системой.

Например, типичный настольный компьютер с Linux поддерживает файловую систему ext3 на имеющемся жестком диске, а также файловую систему ISO 9660 на имеющемся CD-ROM (другое название —CD-ROM file system, CDFS). Поскольку компакт-диски то вставляются, то извлекаются, ядро Linux должно подстраиваться под эти новые файловые системы с различным содержимым и структурой. Также может иметь место доступ к удаленной файловой системе с помощью Network File System (NFS). В то же время Linux может монтировать раздел с файловой системой NT File System (NTFS) с локального жесткого диска системы с двойной загрузкой (Windows® или Linux) и осуществлять чтение или запись на неё.

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

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

Слои (уровни) абстрагирования

Теперь давайте рассмотрим конкретную архитектуру реализации абстрактных функций, предоставляемых VFS в Linux. На рисунке 2 показан общий вид уровней в Linux с точки зрения VFS. Над VFS располагается стандартный интерфейс системных вызовов ядра (standard kernel system-call interface, SCI). Этот интерфейс позволяет передавать вызовы из пространства пользователя в ядро (в разные адресные пространства). В этой области приложение из пространства пользователя, делающее вызов POSIX open, через библиотеку GNU C (glibc) проходит в ядро и в демультиплексор системных вызовов. В конце концов с помощью вызова sys_open вызывается VFS.

Рисунок 2. Структура слоев VFS
Структура слоев VFS

Прежние реализации VFS

Linux не был первой операционной системой, использующей виртуальный уровень для поддержки общей файловой модели. Примерами ранних реализаций VFS являются Sun VFS (в SunOS версии 2.0, приблизительно 1985 год) и Installable File System от IBM и Microsoft® для IBM OS/2. Эти подходы к виртуализации уровня файловой системы проложили дорогу для Linux VFS.

VFS предоставляет уровень абстракции, отделяющий POSIX API от подробностей работы конкретной файловой системы. Ключевым моментом здесь является то, что системные вызовы API Open, Read, Write или Close работают одинаково, независимо от того, какая файловая система располагается ниже: ext3 или Btrfs. VFS предоставляет общую файловую модель, которую наследуют нижележащие файловые системы (они должны реализовать действия для различных функций POSIX API). Дальнейшее абстрагирование, за пределами VFS, скрывает находящееся ниже физическое устройство (которое может являться диском, разделом диска, сетевым модулем хранения, памятью или любым другим носителем, способным хранить информацию—даже временно).

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


Внутренняя организация VFS

Перед рассмотрением общей структуры подсистемы VFS, взглянем на главные используемые объекты. В этом разделе изучаются суперблок (superblock), индексный узел (inode), запись каталога (dentry), и, наконец, объект file. Некоторые другие важные дополнительные элементы, например, кэши, будут рассмотрены позже при рассмотрении общей структуры.

Суперблок

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

На диске суперблок предоставляет ядру информацию о структуре файловой системы на диске. В памяти суперблок предоставляет необходимую информацию и состояние для управления активной (смонтированной) файловой системой. Поскольку Linux поддерживает параллельно несколько одновременно смонтированных файловых систем, каждая структура super_block сохраняется в списке (super_blocks, определяется в ./linux/fs/super.c, а структура определена в /linux/include/fs/fs.h).

На рисунке 3 приводится упрощенный вид суперблока и его элементов. Структура super_block ссылается на ряд других структур, которые содержат другую информацию. Например, структура file_system_type определяет имя файловой системы (например, ext3), а также различные блокировки и функции для получения и удаления super_block. Управление объектами file_system_type осуществляется через хорошо известные функции register_file system и unregister_file system (см. ./linux/fs/file systems.c). Структура super_operations определяет ряд функций для чтения и записи inod’ов, а также для операций более высокого уровня (таких как повторное монтирование). Объект записи корневого каталога (dentry) здесь тоже кэшируется, как и блочное устройство, на котором находится эта файловая система. Наконец, предоставляется число списков для управления объектами inode, в том числе s_inodes (список всех inod’ов), s_dirty (список всех «грязных» inod’ов), s_io и s_more_io (зарегистрированные для отложенной записи) и s_files (список всех открытых файлов для данной файловой системы).

Рисунок 3. Упрощенный вид структуры super_block и связанных с ней элементов
Упрощенный вид структуры super_block и связанных с ней элементов

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

Индексный узел (inode)

Linux управляет всеми объектами в файловой системе через объект, называемый inode (сокращение от index node). Inode может ссылаться на файл или каталог или символическую ссылку на другой объект. Обратите внимание, что поскольку файлы используются для представления других типов объектов, например, устройств или памяти, inod’ы используются и для их представления.

Обратите также внимание, что inode, который я здесь имею в виду, является inod’ом уровня VFS (inode в памяти). Каждая файловая система также включает в себя inode, который находится на диске и предоставляет сведения об объекте, характерном для конкретной файловой системы.

Inod’ы VFS размещаются с помощью механизма распределения памяти slab (из inode_cache; см. ссылку в разделе Ресурсы для дополнительной информации по распределителю slab). Inode состоит из данных и операций, которые описывают inode, его содержимое и различные операции, которые на нем возможны. На рисунке 4 приведена простая иллюстрация inod’а VFS, состоящего из ряда списков, один из которых ссылается на записи dentry, которые ссылаются на этот inode. Сюда входят метаданные объектного уровня, состоящие из знакомых атрибутов времени (время создания, время доступа, время изменения), а также данные о принадлежности владельцу и о правах доступа (идентификатор группы, идентификатор пользователя и права доступа). Inode ссылается на файловые операции, которые возможны на нем, большинство из которых непосредственно отображаются на интерфейсы системных вызовов (например, open, read, write и flush). Есть также ссылка на относящиеся к inod’у операции (create, lookup, link, mkdir и так далее). Наконец, есть структура для управления фактическими данными для объекта, который представлен объектом адресного пространства. Объект адресного пространства— это такой объект, который управляет различными страницами для inod’а в кэше страниц. Объект адресного пространства используется для управления страницами для файла, а также для отображения секций файла на индивидуальные адресные пространства. Объект адресного пространства существует со своим собственным набором операций (writepage, readpage, releasepage и так далее).

Рисунок 4. Упрощенное представление inod’а VFS
Упрощенное представление inod’а VFS

Обратите внимание, что всю эту информацию можно найти в ./linux/include/linux/fs.h.

Запись каталога (dentry)

Иерархическая природа файловой системы управляется другим объектом в VFS, называемым dentry. В файловой системе имеется одна корневая запись dentry (на которую имеется ссылка в системном блоке), причем это единственная запись dentry без родителя. У всех других записей dentry есть родители, а у некоторых — потомки. Например, при открытии файла, составленного из /home/user/name, создается четыре dentry-объекта: один для корня /, один для записи home корневого каталога, один для записи name каталога user и, наконец, один для записи name в каталоге user. Таким образом, записи dentry четко отображаются на иерархические файловые системы, используемые сегодня.

Объект dentry определяется структурой dentry (в ./linux/include/fs/dcache.h). Она состоит из ряда элементов, которые отслеживают связь данной записи с другими записями в файловой системе, а также физическими данными (такими как имя файла). Упрощенный вид dentry-объекта приведен на рисунке 5. Объект dentry ссылается на super_block, который определяет конкретный экземпляр файловой системы, в котором содержится этот объект. Затем идет родительская запись dentry (родительский каталог) объекта, за ней дочерние записи dentry, содержащиеся в списке (если объект оказывается каталогом). Затем определяются операции для dentry (состоящие из таких операций, как hash, compare, delete, release и так далее). Затем определяется имя объекта, которое здесь хранится в записи dentry вместо самого inod’а. Наконец, дается ссылка на inode VFS.

Рисунок 5. Упрощенное представление dentry-объекта
Упрощенное представление dentry-объекта

Заметьте, что dentry-объекты существуют только в памяти файловой системы и не хранятся на диске. Постоянно хранятся только inod’ы, а dentry-объекты используются для повышения производительности. Полное описание структуры dentry можно посмотреть в ./linux/include/dcache.h.

Объект file

Для каждого открытого в Linux-системе файла существует объект file. Этот объект содержит информацию, относящуюся к открытому экземпляру для данного пользователя. Очень упрощенный вид file-объекта представлен на рисунке 6. Как можно видеть, структура path содержит ссылку и на dentry, и на vfsmount. Для каждого файла определен набор файловых операций; это хорошо известные файловые операции (open, close, read, write, flush и так далее). Определен набор флагов и полномочий (включая группу и владельца). Наконец, для конкретного экземпляра файла определяются данные, хранящие состояние, например, текущее смещение в файле.

Рисунок 6. Упрощенное представление объекта file
Упрощенное представление объекта file

Связи объектов

Теперь, рассмотрев различные важные объекты в слое VFS, давайте посмотрим, как они связаны между собой на одной схеме. Исследовав объект снизу вверх, взглянем теперь в обратном направлении, с точки зрения пользователя (см. рисунок 7).

Наверху находится открытый объект file, на который ссылается список файловых дескрипторов процесса. Объект file ссылается на объект dentry, который ссылается на inode. Оба объекта, и inode и dentry, ссылаются на лежащий ниже объект super_block. Несколько file-объектов могут ссылаться на один и тот же dentry (например, в случае, когда два пользователя совместно используют один и тот же файл). Обратите внимание также, что на рисунке 7 объект dentry ссылается на другой объект dentry. В этом случае каталог ссылается на файл, который, в свою очередь, ссылается на inode для конкретного файла.

Рисунок 7. Связи основных объектов в VFS
Связи основных объектов в VFS

Архитектура VFS

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

Рисунок 8. Обобщенный вид слоя VFS
Обобщенный вид слоя VFS

Два главных объекта, которые динамически поддерживаются в VFS, — это объекты dentry и inode. Они кэшируются для ускорения доступа к лежащим ниже файловых системам. Когда файл открывается, кэш dentry заполняется записями, представляющими уровни каталогов, составляющих путь к файлу. Также для объекта создается inode, представляющий файл. Кэш dentry строится с помощью хеш-таблицы и хешируется по имени объекта. Записи для кэша dentry размещаются в dentry_cache с помощью распределителя памяти slab; когда появляется нехватка памяти, для удаления записей используется алгоритм вытеснения по давности использования. Функции, связанные с кэшем dentry, можно найти в ./linux/fs/dcache.c (и ./linux/include/linux/dcache.h).

Кэш inode-объектов реализован в виде двух списков и хеш-таблицы для ускорения поиска. В первом списке определяются inod’ы, которые используются в данное время; во втором списке определяются неиспользуемые inod’ы. Используемые inod’ы хранятся также в хеш-таблице. Отдельные объекты кэшей inod’ов размещаются из inode_cache с помощью распределителя памяти slab. Функции, относящиеся к кэшу inod’ов, можно найти в ./linux/fs/inode.c (и ./linux/include/fs.h). В нынешней реализации кэш inod’ов зависит от кэша dentry. При существующем объекте dentry в кэше inod’ов существует и объект inode. Поиски выполняются в кэше dentry, что в итоге приводит к объекту в кэше inod’ов.


Дополнительные сведения

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

Ресурсы

Научиться

Получить продукты и технологии

  • Используйте в своем следующем проекте разработки для Linux ознакомительное ПО IBM, которое можно загрузить непосредственно с сайта developerWorks. (EN)

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


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

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux
ArticleID=627481
ArticleTitle=Анатомия виртуального коммутатора файловых систем Linux
publish-date=02172011