Виртуальная файловая система (VFS, Virtual File System, в русских учебниках встречается сокращение ВФС) - часть ядра операционной системы, через которую программы одинаково работают с любыми файловыми системами. Приложение вызывает open(), read() или write() и не знает, где лежит файл: на ext4, на флешке с FAT32, в сетевой папке NFS или вообще в оперативной памяти. Разницу берёт на себя VFS: она принимает вызов и передаёт его драйверу нужной файловой системы.
Ниже разберём, как VFS устроена в Linux и других ОС, откуда она взялась, что такое /proc, tmpfs, FUSE и overlayfs и как отвечать на типовые вопросы по VFS из тестов по операционным системам.
Обычная файловая система решает одну задачу: превращает блоки диска в файлы с именами. Для этого она хранит:
У ext4, NTFS, XFS и FAT32 эти структуры устроены по-своему, и на диске они несовместимы. Подробнее о том, как устроена файловая система на обычном диске, мы писали отдельно. Главное здесь: форматов много, а программе нужен один способ работать со всеми. Эту задачу и решает виртуальная файловая система.
VFS - программный слой в ядре ОС между системными вызовами и драйверами конкретных файловых систем. Она задаёт общий набор операций (открыть, прочитать, записать, создать каталог, переименовать, получить атрибуты), а каждая файловая система реализует эти операции под свой формат.
| Уровень | Что там происходит | Пример |
|---|---|---|
| Приложение | Вызывает функции работы с файлами | cat, nginx, 1С, СУБД |
| Системные вызовы | Переход из программы в ядро | open(), read(), write(), stat() |
| VFS | Разбирает путь, проверяет права, ищет в кэшах, выбирает драйвер | Общий код ядра |
| Драйвер файловой системы | Переводит операцию в структуры своего формата | ext4, XFS, Btrfs, клиент NFS, tmpfs |
| Блочный уровень или сеть | Читает и пишет блоки на диск или отправляет запрос серверу | NVMe, SATA, RAID, TCP |
Слово «виртуальная» здесь значит одно: у VFS нет собственного формата на диске. Это интерфейс и набор общих структур в памяти ядра. Так что «отформатировать диск в VFS» нельзя: форматируют в ext4 или NTFS, а VFS работает с любой из них.
Ранние версии UNIX умели работать с одной файловой системой, и код ядра обращался к её структурам напрямую. Проблема появилась, когда понадобилось открывать файлы с других машин по сети.
В 1985 году Sun Microsystems выпустила SunOS 2.0 с сетевой файловой системой NFS. Чтобы локальная UFS и удалённая NFS открывались одними и теми же системными вызовами, инженеры Sun разделили ядро на общую часть и драйверы файловых систем. Архитектуру описал Стив Клейман в докладе «Vnodes: An Architecture for Multiple File System Types in Sun UNIX» на конференции USENIX летом 1986 года. Каждая смонтированная файловая система в ней описывается объектом vfs, каждый файл или каталог - объектом vnode (виртуальным узлом) со своей таблицей операций.
Дальше идея разошлась по всем UNIX-системам. В конце 1980-х VFS по образцу SunOS вошла в System V Release 4, в начале 1990-х свою реализацию vnode получила BSD, от неё ведут родословную FreeBSD и ядро macOS. В Linux VFS с объектами superblock, inode, dentry и file развивалась с 1990-х. В Windows NT с первой версии 1993 года ту же роль играет диспетчер ввода-вывода с подключаемыми файловыми системами NTFS, FAT и CDFS.
VFS - подсистема ядра, то есть обычный программный код, никакого отдельного устройства за ней нет. У неё две задачи, которые в учебниках по ОС называют главными функциями уровня VFS:
Технически каждая файловая система регистрируется в VFS и передаёт ей таблицы функций: как прочитать суперблок, как найти имя в каталоге, как прочитать кусок файла. Ядро вызывает эти функции через указатели, примерно как методы интерфейса в объектно-ориентированном языке. Драйвер бывает встроен в ядро или загружается модулем: в Linux модули ext4, xfs или nfs подгружаются при первом монтировании.
Linux. VFS - центр файловой подсистемы ядра. Через неё работают дисковые файловые системы (ext4, XFS, Btrfs), сетевые (NFS, SMB), псевдо-файловые (/proc, /sys) и FUSE. Команда cat /proc/filesystems покажет, какие типы файловых систем ядро знает прямо сейчас.
Windows. Слоя под названием VFS там нет, ту же роль играет диспетчер ввода-вывода (I/O Manager). NTFS, FAT, exFAT и ReFS - драйверы, которые получают от него запросы. Между ними и диспетчером встают фильтр-драйверы: так перехватывают операции с файлами антивирусы, средства шифрования, резервного копирования и облачные клиенты. Свою файловую систему в пространстве пользователя под Windows пишут на WinFsp или Dokan - это аналоги FUSE.
macOS и FreeBSD. Наследники vnode-архитектуры BSD. APFS, HFS+ и клиент SMB подключены через vnode-интерфейс, пользовательские файловые системы - через macFUSE.
Android. Внутри ядро Linux, значит, и VFS та же. Системные разделы монтируются только для чтения, а начиная с Android 11 доступ приложений к общему хранилищу идёт через FUSE: так система проверяет, к каким файлам приложение пускать.
На серверах это работает так же. Samba и NFS-сервер раздают каталоги через те же системные вызовы, что и любая программа, и им безразлично, что лежит под общей папкой: ext4, XFS или ZFS. Как клиенты потом подключаются к хранилищу, разобрано в статье о протоколах доступа к данным в СХД.
Возьмём Linux, там структура VFS подробно описана в документации ядра. Основных объектов четыре.
| Объект | Что описывает | Сколько их |
|---|---|---|
| superblock | Смонтированную файловую систему целиком: тип, размер блока, корневой каталог, параметры | Один на экземпляр файловой системы |
| inode | Файл или каталог: размер, владелец, права, время, где лежат данные | Один на файл, номер видно в ls -i |
| dentry | Элемент пути: связь имени с inode | Живут в кэше в памяти, на диске своей записи нет |
| file | Файл, открытый процессом: позиция чтения, режим открытия | Создаётся при open(), исчезает после close() |
У каждого объекта есть таблица операций (super_operations, inode_operations, file_operations), её заполняет драйвер файловой системы. Над объектами file стоит таблица файловых дескрипторов процесса: число 3, 4 или 5, которое возвращает open(), - номер ячейки в этой таблице.
Вторая половина структуры - кэши. Кэш записей каталогов (dcache) хранит недавно разобранные пути, и повторное открытие того же файла не ходит на диск. Кэш inode держит метаданные. Страничный кэш (page cache) хранит содержимое файлов в свободной оперативной памяти. Из-за него на сервере с базой данных команда free показывает почти всю память в графе buff/cache, и это нормально: ядро отдаст эту память программам, как только она понадобится.
Проследим, что происходит, когда программа читает файл /srv/share/report.xlsx.
Права проверяются в общем коде: владелец, группа и биты rwx одинаково работают на ext4 и XFS, а драйвер может добавить свои правила, как это делают NFS или списки ACL. Как этими правами управлять, рассказано в статье про права доступа к файлам в Linux.
Все операции с файлами проходят через VFS, на этом уровне за ними и удобно следить. В Linux для этого три механизма.
| Механизм | Что умеет | Где применяют |
|---|---|---|
| inotify | Сообщает программе о событиях в выбранных каталогах: создание, изменение, удаление, переименование | Синхронизация файлов, перезапуск сервиса после правки конфига, утилита inotifywait в скриптах |
| fanotify | Следит за целой файловой системой и может разрешить или запретить доступ до открытия файла | Антивирусы, контроль целостности |
| auditd | Пишет в журнал, кто и когда открыл, изменил или удалил файл | Расследование инцидентов, требования по безопасности |
У inotify есть ограничение, на которое натыкаются на больших файловых серверах: число отслеживаемых объектов задаёт параметр fs.inotify.max_user_watches, и при сотнях тысяч каталогов его приходится поднимать. И ещё inotify не видит изменений, которые сделала другая машина в сетевой папке.
В Windows ту же задачу решают фильтр-драйверы и встроенный аудит доступа к объектам. Как настроить журнал изменений на файловом сервере компании, мы разбирали в статье об аудите файлов на файловом сервере.

Тут два варианта. Первый - форматы, которые в принципе не умеют писать: образ собирают один раз и дальше только читают.
Второй вариант - обычная ext4 или XFS, смонтированная с опцией ro. Запрет на запись VFS проверяет ещё до вызова драйвера. Так монтируют разделы с системными файлами в защищённых сборках. Так же ядро само переводит ext4 в режим чтения при серьёзной ошибке, чтобы не испортить данные ещё сильнее: в Debian и Ubuntu для корневого раздела это задано по умолчанию опцией errors=remount-ro в /etc/fstab.
Режим «только чтение» защищает от случайной перезаписи и части вредоносных программ, но резервную копию не заменяет: root перемонтирует раздел на запись одной командой.
Оба механизма работают на уровне VFS и ничего никуда не копируют и не перемещают.
Bind-монтирование показывает тот же каталог по второму пути: mount --bind /srv/data /home/user/data. Файлы физически лежат в одном месте, изменения сразу видны по обоим путям. Это пригождается, когда программа ищет файлы по жёстко заданному пути, когда каталог нужно пробросить в chroot или контейнер (тома Docker с хоста подключаются именно так) или открыть только часть дерева. Bind-копию можно сделать только для чтения, а исходный каталог останется доступным на запись.
Overlayfs (в ядре Linux с версии 3.18, 2014 год) склеивает несколько каталогов в один. Нижние слои доступны только для чтения, верхний - для записи, программа видит объединённое дерево. Когда программа меняет файл из нижнего слоя, он сначала копируется наверх. Удалённый файл отмечается в верхнем слое специальной пометкой, нижний слой остаётся нетронутым.
На overlayfs построены образы Docker и Podman: слои образа - нижние каталоги, у каждого контейнера свой верхний слой. Поэтому десять контейнеров из одного образа не занимают на диске в десять раз больше места. Чем отличаются контейнеры Docker и LXC, смотрите в сравнении технологий контейнеризации.
Каталог в любой файловой системе - особый файл со списком «имя → ссылка на объект». В ext4 ссылка - номер inode, в NTFS - номер записи в главной таблице MFT. Отличается только то, как этот список хранят и как в нём ищут.
| Файловая система | Как хранится каталог | Как ищется имя |
|---|---|---|
| FAT32 | Массив записей по 32 байта, длинные имена - в дополнительных записях | Перебором по порядку |
| ext4 | Список записей, у больших каталогов - хэш-индекс htree | По хэшу имени |
| NTFS | Индекс имён в виде B+-дерева | По дереву |
| XFS, Btrfs | B-деревья | По дереву |
| ZFS | Хэш-таблица ZAP | По хэшу имени |
На FAT32 в папке с десятками тысяч файлов каждый поиск имени заметно тормозит, да и больше примерно 65 тысяч записей в одну папку она не вместит. На ext4 и XFS такой каталог работает без проблем. Над всем этим у VFS свой кэш dcache: часто используемые пути разбираются в памяти, без обращения к драйверу. «Папка» в проводнике Windows или Finder в macOS - тот же каталог файловой системы NTFS или APFS со своим индексом.
Файловая система должна помнить, в каких блоках диска лежит каждый файл. Классических способов четыре, и все они встречаются в реальных системах.
| Метод | Как работает | Где | Плюсы и минусы |
|---|---|---|---|
| Непрерывное размещение | Файл занимает блоки подряд, достаточно знать начало и длину | ISO 9660, CD и DVD | Быстро читать, но файл трудно увеличить |
| Связный список | В таблице FAT для каждого кластера записан номер следующего кластера файла | FAT12, FAT16, FAT32 | Просто, но до середины файла приходится идти по цепочке; быстро фрагментируется |
| Индексное (inode) | В inode хранится список блоков, у больших файлов - через косвенные блоки со ссылками | ext2, ext3, UFS | Быстрый доступ к любому месту файла, но большому файлу нужно много ссылок |
| Экстенты и деревья | Запись «с блока N подряд M блоков»; у больших файлов такие записи или указатели на блоки собраны в дерево | Экстенты: ext4, XFS, NTFS. Деревья указателей на блоки: Btrfs, ZFS, APFS | Компактно для больших файлов; в Btrfs, ZFS и APFS изменения пишутся в новое место (copy-on-write), отсюда снимки |
Иногда пишут, что ZFS и Btrfs ищут файлы на диске по хэш-таблицам. Это ошибка: данные в обеих адресуются через деревья указателей на блоки. Хэши в ZFS есть, но в каталогах (ZAP), а контрольные суммы блоков нужны для проверки целостности. Как ZFS хранит данные и кому она подходит, рассказано в статье про файловую систему ZFS.
У каждого процесса ядро хранит два каталога: текущий (cwd) и корневой (root). Относительный путь вроде logs/app.log VFS отсчитывает от текущего, абсолютный вроде /etc/hosts - от корневого.
Текущий каталог меняют системным вызовом chdir(), в оболочке это команда cd. Посмотреть оба каталога у работающего процесса можно через /proc: ls -l /proc/.
Корневой каталог у большинства процессов - настоящий /. Его меняют вызовом chroot(): после этого процесс видит только поддерево и подняться выше не может. На этом раньше строили изоляцию FTP-серверов и сборочных окружений. Контейнеры идут дальше: кроме своего корня, они получают отдельное пространство имён монтирования, то есть собственный набор точек монтирования. Сам по себе chroot от процесса с правами root внутри не защищает, для безопасности его мало.
У вопроса два смысла.
Если речь о VFS как о слое ядра, то сама она на диске не хранится. ext4, NTFS, FAT32 и XFS подключаются к ней как драйверы, и ни одна из них в этом смысле не «виртуальная».
Во втором смысле виртуальными называют псевдо-файловые системы, у которых вообще нет диска. Файлы в них создаёт ядро или программа на лету.
| Файловая система | Где обычно смонтирована | Что внутри |
|---|---|---|
| procfs | /proc | Процессы и параметры ядра: /proc/cpuinfo, /proc/meminfo, /proc/ |
| sysfs | /sys | Устройства, драйверы и их настройки, например планировщик ввода-вывода диска |
| tmpfs | /run, /dev/shm, во многих дистрибутивах и /tmp (в Debian - с 13-й версии) | Обычные файлы, но в оперативной памяти и swap; после перезагрузки пропадают |
| devtmpfs | /dev | Файлы устройств: /dev/sda, /dev/nvme0n1 |
| cgroup2 | /sys/fs/cgroup | Ограничения ресурсов для сервисов и контейнеров |
| FUSE | Любая точка монтирования | Файловая система, которую реализует обычная программа: sshfs, rclone mount, ntfs-3g |
Запись в такой файл - команда ядру. echo 1 > /proc/sys/net/ipv4/ip_forward включает пересылку пакетов между сетевыми интерфейсами, и на диск ничего не пишется.
VFS, VMFS и виртуальный диск - не путать
VMFS (Virtual Machine File System) - кластерная файловая система VMware ESXi, на которой хранятся виртуальные машины на общем хранилище. У неё есть свой формат на диске, с VFS общего только похожее название. Виртуальный диск ВМ (файлы .vmdk, .qcow2, .vhdx) - тоже другое: это файл, внутри которого гостевая ОС создаёт свою файловую систему, и с ней уже работает VFS гостевого ядра.
| Параметр | FAT32 | NTFS |
|---|---|---|
| Размер файла | Чуть меньше 4 ГБ | Сотни терабайт и больше, упирается в размер тома |
| Размер тома | До 2 ТБ при секторе 512 байт; штатное форматирование Windows долгое время создавало тома не больше 32 ГБ | До 256 ТБ при кластере 64 КБ, в Windows 10 и новее с кластером 2 МБ - до 8 ПБ |
| Права доступа | Нет | Списки ACL на файлы и папки |
| Журнал | Нет, после сбоя питания нужна проверка диска | Есть журнал метаданных |
| Сжатие, шифрование, квоты, жёсткие ссылки | Нет | Есть |
| Совместимость | Почти везде: телевизоры, камеры, загрузочные флешки UEFI | Windows полностью; Linux - через драйвер ntfs3 в ядре; macOS без сторонних драйверов только читает |
| Где уместна | Флешки, загрузочный раздел EFI | Системный диск Windows, данные, файловые серверы на Windows |
Для флешек и внешних дисков, которые нужны и в Windows, и в macOS, обычно берут exFAT: ограничения в 4 ГБ на файл у неё нет.
Под этим запросом ищут две вещи.
Программисты подменяют настоящий диск файловой системой в памяти, чтобы тесты не трогали реальные файлы, шли быстро и одинаково вели себя на любой машине. Для популярных языков есть готовые библиотеки: pyfakefs для Python, Jimfs от Google для Java, memfs для Node.js, vfsStream для PHP, fstest.MapFS из стандартной библиотеки и afero для Go.
С VFS ядра у них общее только название: такая библиотека подменяет файловые функции внутри одной программы. Если тесту нужна настоящая файловая система, но без риска для данных, монтируют tmpfs или образ диска через loop-устройство.
Вторая часть запросов - вопросы из тестов по операционным системам. Коротко по частым:
| Вопрос | Ответ |
|---|---|
| Что такое VFS? | Слой ядра ОС, который даёт программам единый интерфейс ко всем файловым системам и передаёт вызовы их драйверам |
| Как расшифровывается VFS (ВФС)? | Virtual File System - виртуальная файловая система |
| Какие две главные функции у уровня VFS? | 1) Отделяет общие файловые операции от их реализации, поэтому в одной системе одновременно работают несколько типов файловых систем. 2) Даёт единое представление файла в системе и в сети через vnode |
| Что VFS использует для представления файлов? | Виртуальный узел vnode (в Linux - inode в памяти ядра), для открытого файла - объект file |
| Какие файловые системы поддерживает виртуальный слой? | Любые, для которых есть драйвер: UFS, ext4, NTFS, FAT, сетевые NFS и SMB |
| Зачем виртуальные файловые системы в Linux? | Единый доступ к дисковым и сетевым ФС; /proc и /sys - интерфейс к ядру; tmpfs - временные файлы в памяти; FUSE - файловые системы в пространстве пользователя; overlayfs - слои контейнеров |
| VFS - это устройство? | Нет, программная подсистема ядра |
Если собрать всё вместе, у обычной дисковой файловой системы есть:
Поверх этого операционная система через VFS добавляет общие для всех механизмы: пути, точки монтирования, проверку прав, дескрипторы открытых файлов и кэши.
Нужен сервер под общие папки?
Поможем собрать файловый сервер под ваши объёмы и число пользователей: подберём диски и RAID, память под кэш, сетевые карты и вариант ОС - Windows Server с NTFS или Linux с XFS либо ZFS. Можно выбрать файловый сервер для офиса в каталоге или написать нам: +7 (800) 551-80-12, info@ittelo.ru. Серверами мы занимаемся больше 11 лет и за это время накопили серьёзную экспертизу. Даём гарантию до 5 лет, берём сервер на постпродажное обслуживание и не пропадаем после отгрузки.