Какие виртуальные файловые системы связанные с устройствами присутствуют в linux

Обновлено: 04.07.2024

Мой неполный перевод Overview of the Linux Virtual File System. Некоторые моменты, по различным причинам, я пока не понимаю, поэтому кое-что привожу в оригинале, как повод для дальнейших размышлений. Другие же моменты, как мне кажется, я понимаю, поэтому дополнил их некоторой информацией.

Введение

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

Системные вызовы VFS open(2) , stat(2) , read(2) , write(2) , chmod(2) и так далее, вызываются из контекста работающего процесса. Filesystem locking описана в Documentation/filesystems/locking.rst . (VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so on are called from a process context. Filesystem locking is described in the document Documentation/filesystems/locking.rst.)

Кэш записей каталога / Directory Entry Cache (dcache)

VFS обеспечивает системные вызовы open(2) , stat(2) , chmod(2) и другие похожие. Аргумент pathname , который передаётся на вход этим системным вызовам, используется VFS-системой для поиска вхождений в кэше записей каталога (называемым также dentry cache, или ещё короче dcache). Это обеспечивает сверхбыстрый механизм трансляции pathname (filename) в определённый dentry . Кэш записей каталога необходим только для увеличения производительности, поэтому он хранится в оперативной памяти и никогда не записывается на диск.

Dentry-кэш предназначен для обзора всего файлового пространства. А так как большинство компьютеров не могут вместить все записи dentry в оперативную память, то некоторое количество записей в dentry-кэше может отсутствовать. Поэтому, иногда в процессе сопоставления частей pathname с соответствующими dentry, VFS-коммутатору, возможно, придётся заодно создать некоторое количество dentry, и только после этого загрузить требуемый inode.

Объект Inode / The Inode Object

Отдельный dentry обычно указывает на inode, который является специальной структурой файловой системы, описывающей её файлы-объекты. Объект inode предоставляет различные сведения о файле ( man 2 stat ). В частности:

  • st_dev – id устройства, содержащего файл;
  • st_ino – номер этой inode в таблице inodes;
  • st_mode – тип объекта ( man 7 inode ):
    • обычный файл с данными;
    • directory;
    • block device;
    • .

    Объект inode не содержит имени файла! Так как в пределах одной файловой системы (POSIX) на один файл может ссылаться больше одной именованной жёсткой ссылки, то имя файла не сохраняется в inode . Вместо этого, в файлах-каталогах (тип directory), в списке содержимого данного каталога, создаётся запись: имя файла (то есть имя жёсткой ссылки) — номер inode. Отсюда следует, что при обнулении поля st_nlink в структуре какого-либо inode , соответствующие блоки файловой системы будут помечены свободными и файл можно считать удалённым.

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

    Для поиска какого-либо inode необходимо, чтобы для его родительского inode-каталога, VFS вызвала метод lookup() . Этот метод установлен конкретной реализацией ФС, к которой относится требуемый inode. (This method is installed by the specific filesystem implementation that the inode lives in.) С момента получения VFS-коммутатором dentry (а следовательно и соответствующего inode), мы можем делать с ним всякие скучные вещи, типа открыть файл посредством системного вызова open(2) , или получить данные inode через stat(2) . Из пользовательского пространства системный вызов stat(2) работает довольно просто: как только VFS заимел соответствующий dentry, он передаёт данные из inode обратно в userspace (The stat(2) operation is fairly simple: once the VFS has the dentry, it peeks at the inode data and passes some of it back to userspace.).

    Объект File / The File Object

    Открытие какого-либо файла требует ещё одной операции: выделение файловой структуры (это реализация файловых дескрипторов на стороне ядра). Свеже выделенная файловая структура инициализируется с указателем на соответствующий dentry и на набор файловых операций функций-членов. (The freshly allocated file structure is initialized with a pointer to the dentry and a set of file operation member functions.) Они берутся из сведений, содержащихся в соответствующей inode. Применяемый к файлу метод open() вызывается тогда, как только конкретная реализация файловой системы сможет сделать это. Вы можете видеть, что это ещё одна функция выполняемая VFS-коммутатором. Файловая структура помещается в таблицу дескрипторов файлов для вызывающего процесса.

    Чтение, запись и закрытие файла (и другие подобные операции VFS) осуществляются с помощью соответствующих методов, перечисленных в подходящей к требуемому файлу файловой структуре, каковая структура становится доступной из пространства пользователя через использование конкретного файлового дескриптора. Dentry остаётся в использовании, пока файл открыт, что, в свою очередь, означает, что VFS inode остаётся в использовании.

    Процедура регистрации типа файловой системы в ядре Linux, и процедура отмены регистрации, используют следующие функции API:

    Передающийся struct file_system_type описывает вашу ФС. Когда запрашивается монтирование тома какой-либо ФС к каталогу в вашем пространстве имён, то VFS вызывет подходящий метод монтирования для конкретной ФС. Новый vfsmount, ссылающийся на дерево, возвращаемое ->mount(), будет подсоединён к точке монтирования, так что когда в процессе разбора pathname будет достигнута точка монтирования, то будет совершён переход внутрь vfsmount, на его корень.

    struct file_system_type

    Эта структура описывает файловую систему. Начиная с kernel 2.6.39, определены следующие элементы struct :

    name
    - наименование типа файловой системы, например как "ext2", "iso9660", "msdos" и прочее.

    fs_flags
    - различные флаги (то есть, FS_REQUIRES_DEV, FS_NO_DCACHE, и т.д.)

    mount
    - метод, вызов которого производится при монтировании нового экземпляра файловой системы

    kill_sb
    - метод, вызов которого производится при размонтировании экземпляра файловой системы

    owner
    - для внутреннего использования VFS: в большинстве случаев вы должны инициализировать это через THIS_MODULE

    next
    - для внутреннего использования VFS: вы должны инициализировать это в NULL

    s_lock_key, s_umount_key: lockdep-specific

    Метод mount() имеет следующие аргументы:
    struct file_system_type *fs_type
    - описывает файловую систему, частично инициализируется определённым кодом файловой системы

    int flags
    - флаги монтирования

    const char *dev_name
    - монтируемое имя устройства

    void *data
    - различные опции в виде ASCII-строки, указываемые при монтировании (смотри раздел “Mount Options”)

    При вызове, метод mount() должен возвращать корневой dentry запрошенного дерева каталогов. Вызывающий процесс должен захватить ссылку на суперблок ФС, и суперблок должен быть заблокирован. При ошибке, метод возвращает указатель ERR_PTR (ошибка).

    Аргументы соответствуют таковым из mount(2) и их интерпретация зависит от типа ФС. Например, для блочной файловой системы, dev_name интерпретируется как имя блочного устройства, и устойство это открыто, и оно содержит подходящую файловую систему, для которой метод mount() создаёт и инициализирует соответствующий struct super_block , и возвращает корневой dentry вызывающему процессу.

    Объект super_block

    Объект superblock представляет монтированную файловую систему.

    struct super_operations

    Эта структура описывает как VFS может манипулировать суперблоком вашей файловой системы. Начиная с kernel 2.6.22, определены следующие элементы:

    Все методы вызываются без каких-либо удерживаемых? (being held) блокировок, если не указано иное. Это означает, что большинство методов можно безопасно блокировать. Все методы вызываются только из контекста процесса (то есть не из обработчика прерываний или ниже (bottom half)).

    Объект Inode

    Объект inode представляет объект внутри файловой системы.

    struct inode_operations

    Эта структура описывает, как VFS может манипулировать inode'ом в вашей файловой системе. Начиная с kernel 2.6.22, определены следующие элементы:

    И опять, все методы вызываются без каких-либо блокировок, если не указано иное.

    Объект Адресное Пространство

    Объект адресное пространство используется для группирования и управления страницами в страничном кэше (page cache). Он может быть использован для отслеживания страниц в файле и отслеживания отображения секция файла в адресное пространство процесса.

    Обработка ошибок в течении writeback

    Большинство приложений, которые буферизуют операции чтения/записи, периодически синхронизируют файл вызовом (fsync, fdatasync, msync or sync_file_range), чтобы быть уверенным, что данные в буфере сброшены обратно на устройство хранения. .

    struct address_space_operations

    Эта структура описывает, как VFS может манипулировать отображением файла в страничном кэше в вашей файловой системе. Определены следующие элементы структуры:

    writepage
    - вызывается Виртуальной Машиной для сброса черновых страниц обратно в хранилище. Это может случаться для сохранения целостности данных ( sync ), или для освобождения памяти (flush).

    readpage
    - вызывается Виртуальной Машиной при чтении страницы из хранилища. Эта страница будет заблокирована во время вызова readpage , и должна быть разблокирована и промаркирована, как uptodate, с момента завершения чтения. Если ->readpage обнаруживает, что требуется разблокировка страницы по какой-либо причине, то он может сделать это, но вернув AOP_TRUNCATED_PAGE. В этом случае страница будет relocated, relocked и, если всё успешно будет выполнено, то вызов ->readpage будет повторён.

    writepages
    - вызывается Виртуальной Машиной для сброса на диск всех страниц, ассоциированных с адресным пространством объекта.

    Объект Файл

    Файловый объект представляет файл, открытый процессом. Он также известен, как файловый дескриптор (open file description) в POSIX-диалекте.

    struct file_operations

    Эта структура описывает, как VFS может манипулировать открытым файлом. Начиная с kernel 4.18, определены следующие элементы:

    Again, all methods are called without any locks being held, unless otherwise noted.

    llseek
    - вызывается, когда VFS нуждается в перемещении file position index

    read
    - называется read(2) и относится к системным вызовам
    .

    Directory Entry Cache (dcache)

    struct dentry_operations

    Эта структура описывает, как файловая система может перегружать стандартные dentry операции.

    Directory Entry Cache API

    There are a number of functions defined which permit a filesystem to manipulate dentries:

    Mount Options

    Parsing options

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

    The header defines an API that helps parse these options. There are plenty of examples on how to use it in existing filesystems.

    Showing options

    Если файловая система приняла опции, то она должна определить show_options(), для показа всех актуальных текущих опций. Правила показа:

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

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

    Оригинал: Virtual filesystems in Linux: Why we need them and how they work
    Автор: Alison Chaiken
    Дата публикации: 8 марта 2019 года
    Перевод: А. Кривошей
    Дата перевода: май 2019 г.

    Что такое файловая система? По словам Роберта Лава , «файловая система - это иерархическое хранилище данных, привязанных к определенной структуре». Однако это описание одинаково хорошо применимо к VFAT (виртуальная таблица размещения файлов), Git и Cassandra (база данных NoSQL). Так что же отличает файловую систему?

    Основы файловых систем

    Ядро Linux требует, чтобы сущность, которая считается файловой системой, должна реализовывать методы open(), read() и write() для постоянных объектов, имеющих название. С точки зрения объектно-ориентированного программирования ядро рассматривает общую файловую систему как абстрактный интерфейс, и эти три главные функции являются «виртуальными», без определения по умолчанию. Соответственно, стандартная реализация файловой системы ядра называется виртуальной файловой системой (VFS).

    Если мы можем выполнить open(), read(), and write(), то сущность является файлом, как показывает этот сеанс терминала.

    VFS лежит в основе известного наблюдения, что в Unix-подобных системах «все является файлом». Подумайте, как странно, что крошечное демо с символьным устройством /dev/console на самом деле работает. Изображение показывает интерактивный сеанс Bash по виртуальному телетайпу (tty). При отправке строки в устройство виртуальной консоли она появляется на виртуальном экране. VFS имеет другие, даже более странные свойства. Например, в ней можно производить поиск.

    Все известные файловые системы, такие как ext4, NFS и /proc, предоставляют определения функций большой тройки в структуре данных на языке C, называемой file_operations. Кроме того, некоторые файловые системы расширяют и переопределяют функции VFS в рамках объектно-ориентированного подхода. Как указывает Роберт Лав, абстракция VFS позволяет пользователям Linux безболезненно копировать файлы в и из сторонних операционных систем или абстрактных объектов, таких как каналы, не беспокоясь о внутреннем формате данных. От имени пользовательского пространства с помощью системного вызова процесс может копировать из файла в структуры данных ядра с помощью метода read() одной файловой системы, а затем использовать метод write() другого типа файловой системы для вывода данных.

    Определения функций, которые принадлежат самому базовому типу VFS, находятся в файлах fs/*.c в исходном коде ядра, а подкаталоги fs/ содержат определенные файловые системы. Ядро также содержит объекты, подобные файловой системе, такие как cgroups, /dev и tmpfs, которые необходимы на ранних этапах процесса загрузки и поэтому определяются в подкаталоге init/ ядра. Обратите внимание, что cgroups, /dev и tmpfs не вызывают три главные функции file_operations, а вместо этого непосредственно читают и записывают в память.

    Диаграмма ниже примерно иллюстрирует, как пользовательское пространство обращается к различным типам файловых систем, обычно монтируемых в системах Linux. Не показаны такие конструкции, как pipe, dmesg и часы POSIX, которые также реализуют struct file_operations и доступ к которым, следовательно, происходит через уровень VFS.

    уровень VFS

    VFS - это "слой прокладки" между системными вызовами и разработчиками определенных файловых систем, таких как ext4 и procfs. Затем функции file_operations могут взаимодействовать либо с драйверами, специфичными для устройства, либо с аксессорами памяти. tmpfs, devtmpfs и cgroups не используют file_operations, но имеют прямой доступ к памяти.

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

    /tmp: простой совет

    Простой способ выяснить, какие VFS присутствуют в системе, набрать команду mount | grep -v sd | grep -v :/, которая выводит все смонтированные файловые системы, которые не находятся на диске и не являются NFS на большинстве компьютеров. Одной из перечисленных точек монитирования VFS наверняка будет /tmp, верно?

    хранение /tmp на физическом носителе - это безумие

    Все знают, что хранение /tmp на физическом носителе - это безумие!

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

    К сожалению, установочные скрипты для некоторых дистрибутивов Linux по умолчанию создают /tmp на жестком диске. Не отчаивайтесь, если это произойдет с вашей системой. Следуйте простым инструкциям в великолепной Arch Wiki, чтобы решить эту проблему, помня, что память, выделенная для tmpfs, не доступна для других целей. Другими словами, система с гигантскими tmpfs с большими файлами в ней может исчерпать доступную память и зависнуть. Другой совет: при редактировании файла /etc/fstab обязательно заканчивайте его новой строкой, иначе ваша система не загрузится.

    /proc и /sys

    Помимо /tmp, VFS, с которыми большинство пользователей Linux лучше всего знакомы, это /proc и /sys. (/dev полагается на разделяемую память и не использует файловых операций). Почему две файловые системы? Давайте посмотрим их более подробно.

    Procfs предлагает моментальный снимок состояния ядра и процессов, которые оно контролирует для пользовательского пространства. В /proc ядро публикует информацию о предоставляемых им средствах, таких как прерывания, виртуальная память и планировщик. Кроме того, /proc/sys - это место, где параметры, которые можно настроить с помощью команды sysctl, доступны для пользователя. Состояние и статистика по отдельным процессам указываются в каталогах /proc/

    /proc /meminfo

    /proc /meminfo - это пустой файл, который, тем не менее, содержит ценную информацию.

    Поведение файлов в /proc показывает, насколько VFS может отличаться от файловых систем на диске. С одной стороны, /proc/meminfo содержит информацию, представленную командой free. С другой стороны, он также пустой! Как это может быть? Ситуация напоминает известную статью, написанную физиком Корнелльского университета Н. Дэвидом Мермином в 1985 году, под названием «Есть ли луна там, куда никто не смотрит? Реальность и квантовая теория». Правда в том, что ядро собирает статистику о памяти, когда процесс запрашивает его, из /proc, и в файлах /proc фактически ничего нет, когда никто не просматривает их. Как сказал Мермин, «фундаментом квантовой доктрины является то, что измерение, как правило, не выявляет ранее существовавшее значение измеряемого свойства».

    Файлы в /proc пустые

    Файлы в /proc пустые, когда к ним не обращается ни один процесс (источник).

    Кажущаяся пустота procfs имеет смысл, поскольку доступная там информация динамична. Ситуация с sysfs другая. Давайте сравним, сколько файлов размером не менее одного байта существует в /proc и /sys.

    сравнение /proc и /sys

    Procfs имеет именно одну, а именно экспортированную конфигурацию ядра, что является исключением, поскольку его нужно генерировать только один раз при загрузке. С другой стороны, /sys имеет много файлов большего размера, большинство из которых составляют одну страницу памяти. Как правило, файлы sysfs содержат ровно одно число или строку, в отличие от таблиц информации, создаваемой чтением таких файлов, как /proc/meminfo.

    Цель sysfs - предоставить доступ для чтения и записи свойств того, что ядро называет "kobjects", в пространстве пользователя. Единственная цель kobjects - подсчет ссылок: когда последняя ссылка на kobject удаляется, система возвращает связанные с ним ресурсы. Тем не менее, /sys представляет собой большую часть знаменитого «stable ABI to userspace» ядра, которое никто и ни при каких обстоятельствах не может «сломать». Это не означает, что файлы в sysfs являются статическими, что противоречило бы подсчету ссылок изменчивых объектов.

    Вместо этого стабильный ABI ядра ограничивает то, что может появиться в /sys, а не то, что действительно присутствует там в данный момент. Перечисление разрешений для файлов в sysfs дает представление о том, как настраиваемые параметры устройств, модулей, файловых систем и т. д., могут быть заданы или прочитаны. Логика заставляет прийти к заключению, что procfs также является частью стабильного ABI ядра, хотя в документации ядра это не указано явно.

    «0» в файле показывает, что SSD не является съемным

    Файлы в sysfs описывают ровно одно свойство каждого объекта и могут быть читаемыми, записываемыми или все это вместе. «0» в файле показывает, что SSD не является съемным.

    Отслеживание VFS с помощью утилит eBPF и bcc

    Самый простой способ узнать, как ядро управляет файлами sysfs, - это посмотреть его в действии, а самый простой способ посмотреть это на ARM64 или x86_64 - использовать eBPF. eBPF (extended Berkeley Packet Filter) состоит из виртуальной машины, работающей внутри ядра, которую привилегированные пользователи могут запрашивать из командной строки. Код ядра сообщает читателю, что может сделать ядро; запуск инструментов eBPF в загруженной системе показывает, что фактически делает ядро.

    К счастью, начать работу с eBPF довольно просто с помощью утилит bcc, которые доступны в виде пакетов из основных дистрибутивов Linux и подробно документированы Бренданом Греггом. Утилиты bcc - это скрипты Python с небольшими встроенными фрагментами C, поэтому любой, кто знаком с любым языком, может легко их изменить. На этот счет в bcc/tools есть 80 скриптов Python, поэтому весьма вероятно, что системный администратор или разработчик найдет соответствующий его потребностям.

    Чтобы получить очень общее представление о том, какую работу выполняют VFS в работающей системе, попробуйте скрипты vfscount или vfsstat, которые показывают, что каждую секунду происходят десятки вызовов vfs_open() и подобных ему.

    vfsstat.py - это скрипт Python со встроенным фрагментом C, который просто считает вызовы функций VFS.

    Для менее тривиального примера давайте посмотрим, что происходит в sysfs, когда в работающую систему вставлена USB-флешка.

    vfsstat.py

    Посмотрите с помощью eBPF, что происходит в /sys, когда вставлена флешка.

    Когда вставлен USB-накопитель, появляется обратная трассировка ядра, показывающая, что PID 7711 является потоком kworker, который создал файл с именем «events» в sysfs. Соответствующий вызов sysfs_remove_files() показывает, что удаление флешки приводит к удалению файла events в соответствии с идеей подсчета ссылок. Просмотр sysfs_create_link() с помощью eBPF во время вставки USB-накопителя (не показан) показывает, что создано не менее 48 символических ссылок.

    В любом случае, какова цель файла events? Использование cscope для поиска function __device_add_disk() показывает, что она вызывает disk_add_events(), и либо «media_change», либо «eject_request» могут быть записаны в файл events. Здесь блочный уровень ядра информирует пространство пользователя о появлении и исчезновении «диска». Подумайте, насколько быстро этот метод исследует, как работает вставка USB-накопителя, в сравнении с попыткой изучить этот процесс исключительно из источников.

    Доступные только для чтения корневые файловые системы делают возможными встроенные устройства.

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

    Тем не менее, многие слышали, что большинство IoT и встроенных устройств, такие как маршрутизаторы, термостаты и автомобили, теперь работают под управлением Linux. У многих из этих устройств почти полностью отсутствует пользовательский интерфейс, и нет способа их «чистой» перезагрузки. Подумайте о запуске автомобиля с разряженной батареей, когда питание бортового компьютера под управлением Linux скачет. Как получается, что система загружается без длинного fsck, когда двигатель наконец запускается? Ответ заключается в том, что встроенные устройства используют корневую файловую систему только для чтения (для краткости ro-rootfs).

    ro-rootfs

    ro-rootfs - это то, почему встраиваемые системы часто не нуждаются в fsck.

    Ro-rootfs предлагают множество преимуществ, которые менее очевидны, чем неубиваемость. Одно из них заключается в том, что вредоносные программы не могут писать в /usr или /lib, как и ни один процесс Linux. Другое заключается в том, что неизменяемая файловая система в значительной степени имеет решающее значение для полевой поддержки удаленных устройств, поскольку вспомогательный персонал обладает локальными системами, которые номинально идентичны системам на местах. Возможно, самое важное (но также и самое тонкое) преимущество заключается в том, что ro-rootfs заставляет разработчиков решать на этапе разработки проекта, какие системные объекты будут неизменными. Работа с ro-rootfs часто может быть неудобной или даже болезненной, как это часто бывает с константами в языках программирования, но преимущества легко окупают дополнительные издержки.

    Создание rootfs только для чтения требует дополнительных усилий для разработчиков встраиваемых систем, и именно здесь на помощь приходит VFS. Linux требует, чтобы файлы в /var были доступны для записи, и, кроме того, многие популярные приложения, которые запускаются встраиваемыми системами, будут пытаться создать конфигурационные файлы в $HOME. Одно из решений для конфигурационных файлов в домашнем каталоге, как правило, состоит в том, чтобы сгенерировать их предварительно и встроить в rootfs. Для /var один из подходов заключается в монтировании его в отдельный доступный для записи раздел, а / - только для чтения. Использование монтирования с привязкой и наложением (bind and overlay mounts) является еще одной популярной альтернативой.

    Монтирования с привязкой и наложением, и их использование в контейнерах

    Запуск man mount - лучшее место для изучения монтирования с привязкой и наложением, которое позволяет разработчикам встроенных систем и системным администраторам создавать файловую систему в одном месте, а затем предоставлять ее приложениям в другом. Для встроенных систем это означает, что можно сохранять файлы в /var на неперезаписываемом флэш-устройстве, но накладывать или привязывать-монтировать путь в tmpfs на путь /var при загрузке, чтобы приложения могли просматривать их у себя. При следующем включении изменения в /var исчезнут. Оверлейные монтирования обеспечивают объединение между tmpfs и базовой файловой системой и позволяют вносить видимые изменения в существующий файл в ro-rootfs, в то время как монтирования с привязкой делает так, чтобы новые пустые каталоги tmpfs отображались как доступные для записи в путях ro-rootfs. Хотя overlayfs является подходящим типом файловой системы, монтирование с привязкой осуществляется с помощью средств пространства имен VFS.

    Основываясь на описании оверлеев и связываний, никто не удивится, что контейнеры Linux активно их используют. Давайте посмотрим, что происходит, когда мы используем systemd-nspawn для запуска контейнера, запустив утилиту bcc mountsnoop:

    Вызов system-nspawn

    Вызов system-nspawn запускает контейнер во время работы mountsnoop.py.

    И посмотрим, что случилось:

    Запуск mountsnoop во время «загрузки» контейнера

    Запуск mountsnoop во время «загрузки» контейнера показывает, что среда выполнения контейнера сильно зависит от привязки монтирования (отображается только начало длинного вывода).

    Здесь systemd-nspawn предоставляет выбранные файлы в procfs и sysfs хоста контейнеру по путям в его rootfs. Помимо флага MS_BIND, который устанавливает привязку-монтирование, некоторые другие флаги, которые вызывает системный вызов mount, определяют взаимосвязь между изменениями в пространстве имен хоста и в контейнере. Например, bind-mount может либо распространять изменения в /proc и /sys на контейнер, либо скрывать их, в зависимости от вызова.

    Заключение

    Понимание внутренних возможностей Linux может показаться невыполнимой задачей, поскольку само ядро ​​содержит гигантский объем кода, даже оставляя в стороне приложения пользовательского пространства Linux и интерфейс системных вызовов в библиотеках C, таких как glibc. Один из способов добиться прогресса - это прочитать исходный код одной подсистемы ядра с акцентом на понимание системных вызовов и заголовков, обращенных к пользовательскому пространству, а также основных внутренних интерфейсов ядра, примером которых является таблица file_operations. Файловые операции - это то, что заставляет работать принцип "все - это файл", поэтому особенно полезно получить управление ими. Исходные файлы ядра C в каталоге / верхнего уровня представляют собой реализацию виртуальных файловых систем, которые представляют собой слой, обеспечивающий широкую и относительно прямую совместимость популярных файловых систем и устройств хранения. Монтирование с привязкой и наложением через пространства имен Linux - это магия VFS, которая делает возможными контейнеры и корневые файловые системы только для чтения. В сочетании с изучением исходного кода, набор утилит eBPF и его интерфейс bcc делают исследование ядра более простым, чем когда-либо прежде.

    Структура и типы файловых систем в Linux

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

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

    Файловые системы в операционной системе Linux. Базовые понятия

    ОС Linux предоставляет выбор еще на стадии установки: в ядро системы встроены разные файловые системы (ФС). При этом пользователь должен выбрать ту, что отвечает его требованиям и задачам. Перед теми, кто использует Windows, такой вопрос не стоит — эту ОС можно установить только на NTFS. Отличается от Windows и иерархическое устройство самих ФС, и структура каталогов.

    Linux поддерживает деление жесткого диска на разделы. Для подсчета и определения физических границ используется специальная таблица разделов — GPT или MBR. Она содержит метку и номер раздела, а также адреса физического расположения точек начала и конца раздела.

    Организация файловой системы Linux

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

    От выбора файловой системы зависят:

    • скорость работы с файлами;
    • их сохранность;
    • скорость записи;
    • размер файлов.

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

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

    ФС Linux — пространство раздела, поделенное на блоки определенного размера. Он определяется кратностью размеру сектора. Соответственно, это могут быть 1024, 2048, 4096 или 8120 байт. Важно помнить, что размер каждого блока известен изначально, ограничен максимальным размером ФС и зависит от требований, которые выдвигает пользователь к каждому из блоков.

    Для обмена данными существует сразу два способа. Первый из них — виртуальная файловая система (VFS). С помощью данного типа ФС происходит совместная работа ядра и приложений, установленных в системе. VFS позволяет пользователю работать, не учитывая особенности каждой конкретной ФС. Второй способ — драйверы файловых систем. Именно они отвечают за связь между «железом» и софтом.

    Список файловых систем, которые поддерживаются ядром, находится в файле /proc/filesystems:

    Структура и иерархия файловой системы. Структура каталога

    Файловая система в Linux определяет также организацию расположения файлов, по сути представляя собой иерархическую структуру «дерева»: начинается с корневого каталога «/» и разрастается ветвями в зависимости от работы системы.

    ФС также характерно понятие целостности: в такой системе изменения, внесенные в один файл, не приведут к изменению другого файла, не связанного с первым. У всех данных есть собственная физическая память. В Linux целостность ФС проверяется специальной командой — fsck.

    Типы файлов условно можно разделить на несколько групп. Некоторые из них такие же, как и в ОС Windows, — текстовые документы, медиа и изображения. Отличия начинаются с каталогов, которые являются отдельным типом файлов. Жесткие диски относят к блочным устройствам. Принтеры — к символьным. Отдельную группу составляют символические ссылки, о которых речь пойдет ниже. К типам файлов относится каналы межпроцессного взаимодействия — PIPE (FIFO), а также гнезда (разъемы центрального процессора).

    Тип файла определяется с помощью команды ls (параметр -l).

    В ФС каждый файл определяется конкретным индексом — Inode (от англ. index node — «индексный дескриптор»). Но при этом один файл (речь о физическом размещении) может иметь сразу несколько имен (или путей). И если в структуре ФС файлы будут отличаться, то на жестком диске им может соответствовать один файл. Это означает, что ФС Linux перекрестно-иерархична, а ветви дерева могут пересекаться.

    Корневой раздел в Linux один — «/» (root, «корень)». Разделы называются подкаталогами, примонтированными к соответствующим каталогам. Типовая структура каталогов (первых двух уровней), примонтированных к корневому каталогу Linux для сервера, представленного компанией Selectel, выглядит так:

    При монтировании происходит ассоциирование каталога с устройством, содержащим ФС (драйвер). Соответствующая ссылка на устройство передается драйверу. Именно он и определяет ФС. Если процедура завершается успешно, ядро заносит информацию (каким драйвером обслуживаются и где расположены файлы и каталоги) в таблицу монтирования. Она находится в файле /proc/mounts.

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

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

    Еще одна особенность Linux: существование сразу двух типов ссылок. Во-первых, жесткая ссылка (Hard-Link), которая представляет собой один из путей файла (команда ls -li). Во-вторых, символьная ссылка (Symbolic link) — это файл UNIX с текстовой строкой с путем к оригинальному файлу.

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


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

    Команды для работы с файлами в Linux

    КомандаЧто делает
    lsПросматривает содержимое
    текущего каталога
    touch file_name Создает файл file_name
    mkdir directory_name Создает директорию directory_name
    cat file_name Показывает содержимое файла
    file_name в терминале
    less file_nameОбеспечивает просмотр файла
    с помощью скроллинга
    rm file_name Удаляет файл file_name
    rm -rУдаляет рекурсивно все файлы
    из директории
    rmdir directoryУдаляет папку directory, которая
    находится в текущей папке
    ln -s /home/user/directory_name/ /home/user/test/Создает жесткие и символические
    ссылки на файлы или папки. Для
    создания символической
    ссылки используется опция -s
    pwdВыводит каталога, в котором
    находится пользователь
    which programВыводит каталог, в котором
    установлена программа
    mcЗапускает полнофункциональный
    файловый менеджер
    с псевдографическим
    интерфейсом на основе ncurses.
    Требуется установка mc в Ubuntu
    cd directory_nameПереходит в директорию
    directory_name
    cp file_name directory_name Копирует file_name в директорию
    directory_name
    nanoИнициирует запуск простейшего
    текстового редактора командной
    строки Linux
    mv file_name directory_nameПеремещает file_name в директорию
    directory_name
    mv old_name new_nameПереименовывает файл/директориюold_name в new_name
    locate file_nameВыполняет быстрый поиск файла
    chmod 644 file_nameИзменяет права доступа к файлу или каталогу

    Типы файловых систем Linux. Какая из файловых систем используется ядром Linux

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

    Список основных файловых систем:

    ФС может являться корневой в различных разделах, Linux позволяет использовать разные системы одновременно.

    Ext2, Ext3, Ext4

    Первая группа ФС — Extended Filesystem (Ext2, Ext3, Ext4) — является стандартом для Linux. Как следствие, это самые распространенные системы. Они редко обновляются, но зато стабильны. Ext2 создавалась специально под Linux (изначально Extended Filesystem делали еще под Minix).

    Эта группа ФС поддерживает наибольшее количество доступных функций из всех, предложенных на рынке. Ext3 (2001 г.) стала еще более стабильной, чем ее предшественница, за счет использования журналирования, а версия Ext3 (2006 г.) популярна и среди современных пользователей. Среди улучшений: увеличение максимального размера раздела до 1 Эксабайта.

    Два типа файловых систем

    Журналируемые — данный тип ФС сохраняет историю действий пользователя, а также план проверки системы в специальном файле. Особенности: устойчивость к сбоям и сохранение целостности информации.

    Не журналируемые — не предусматривают хранение логов. Особенности: работают быстрее, но не гарантируют сохранность данных.

    Чтобы узнать тип ФС, существует команда file -s.

    Журналируемая ФС — первая альтернатива для ФС группы Ext. Ее разработали в IBM специально для операционной системы AIX UNIX. Главные плюсы этой системы: стабильность и минимальные требования для работы. Разработчики JFS ставили перед собой цель создать ФС, которая бы эффективно работала на многопроцессорных компьютерах. Кроме того, эта система также относится к журналируемым ФС. Но есть и очевидные недостатки. Если случится непредвиденный сбой в работе системы, ФС может использовать версии файлов, которые уже устарели. Причина заключается в том, что журнал сохраняет только метаданные.

    ReiserFS

    Эта ФС разработана под руководством Ганса Райзера и названа в честь него. Подходит исключительно под Linux, чаще всего ее используют в качестве возможной замены Ext3. Главные особенности: увеличенная производительность и более широкие возможности. Изменяющийся размер блока дает пользователю возможность объединять небольшие файлы в один блок, таким образом удается избежать фрагментации и повысить качество работы ФС в целом. Размер разделов можно менять прямо в процессе работы, однако эта ФС может показать нестабильные результаты и потерять данные, например, при отключении энергии.

    Еще одна журналируемая ФС. Однако, в отличие от аналогов, в логи записывает исключительно те изменения, которые претерпевают метаданные. Разработана для ОС в Silicon Graphics. Важные особенности: быстро работает с файлами сравнительно большого размера, умеет выделять место в отложенном режиме, а также менять размеры разделов в процессе работы. Часто встречается в дистрибутивах на основе Red Hat. Минусы: нельзя уменьшить размер разделов, сложно восстанавливать данные и можно потерять информацию при отключении питания.

    Btrfs

    Современная ФС, главной особенностью которой является высокая отказоустойчивость. Из дополнительных «бонусов»: удобна для сисадминов и поддерживает сравнительно простой процесс восстановления данных. Поддерживает подтома, разрешает менять размеры разделов в динамическом режиме и позволяет делать снапшоты. Отличается высокой производительность. Применяется как ФС, установленная по умолчанию, в OpenSUSE и SUSE Linux. Главный минус — нестабильность (нарушена обратная совместимость, сложная для поддержки и так далее).

    Flash-Friendly File System входит в состав ядра ОС Linux и предназначена для использования с хранилищем на основе флеш-памяти. Разработчик — корпорация Samsung. F2FS разбивает носитель на части, которые снова делятся, и так далее. Эти миниатюрные зоны используются вместо повторного использования одних и тех же размеченных участков.

    OpenZFS

    OpenZFS — ветвь ZFS, о которой мы пишем ниже). Разработчик — компания Sun для ОС Solaris. В 2016 году Ubuntu включила ее поддержку по умолчанию. Главные плюсы: защита от повреждения данных, поддержка больших файлов и автоматическое восстановление.

    Традиционные для Windows ФС NTFS, FAT, HFS применяются в Linux, но пользователь не сможет установить в такие разделы корень, поскольку структура этих ФС для этого не приспособлена.

    Специальные файловые системы

    Для решения задач, связанных с предоставлением доступа пользователю или программам к настройкам ядру ОС, используются так называемые специальные файловые системы. Ядро использует несколько типов специальных ФС:

    • tmpfs — записывает файлы в ОП. Для этого создается блочное устройство определенного объема, после чего оно подключается к папке.
    • procfs — хранит данные о системных процессах и ядре.
    • sysfs — изменяет настройки ядра ОС.

    Виртуальные файловые системы: EncFS, Aufs, NFS и ZFS

    Если пользователю необходимо решить задачи, которые не требуют непременного наличия ФС в ядре, применяется модуль FUSE (filesystem in userspace). Он создает ФС в пространстве пользователя. Виртуальные ФС, как правило, поддерживают шифрование и сетевое администрирование. Сегодня на рынке существует целый спектр виртуальных ФС для ряда задач:

    Читайте также: