Я никогда не слышал об этих акронимах UFDT и GFDT, но ваш взгляд на систему звучит в основном правильно. Я думаю, вам не хватает подробностей о том, как ядро просматривает открытые файлы, и, возможно, именно здесь возникает ваше замешательство. Я попытаюсь дать более подробное описание.
Во-первых, есть три структуры данных, используемые для отслеживания и управления открытыми файлами:
- Каждый процесс имеет таблицу дескрипторов файлов. Каждая запись в этой таблице хранит дескриптор файла и флаги состояния дескриптора файла (на данный момент единственным флагом является
O_CLOEXEC
). Дескриптор файла - это всего лишь указатель на запись в записи таблицы файлов, которую я описываю далее. Целое число, возвращаемое open(2)
, и семейство обычно является индексом в эту файловую дескрипторную таблицу - каждый процесс имеет свою таблицу, поэтому open(2)
и семейство могут возвращать одинаковое значение для разных процессов, открывающих разные файлы.
- Существует одна открытая таблица файлов во всей системе. Каждая запись таблицы дескриптора файла каждого процесса ссылается на одну из этих записей в таблице открытых файлов. В каждой таблице есть одна запись для каждого открытого файла: если два процесса открывают один и тот же файл, создаются две записи в этой глобальной таблице, хотя это один и тот же файл. Каждая запись в таблице файлов хранит флаги состояния файла (открытые для чтения, записи, добавления и т. Д.) И текущее смещение файла. Вот почему разные процессы могут считывать и записывать в разные смещения в одном файле одновременно, пока каждый из них открывает файл.
- Каждая запись в записи таблицы файлов также ссылается на запись в таблице vnode. Таблица vnode - это глобальная таблица, которая имеет одну запись для каждого уникального файла. Если процессы A, B и C открывают файл D, будет существовать только одна запись в таблице vnode, на которую ссылаются все 3 записи таблицы файлов (в Linux нет действительно vnode, скорее, есть индексный дескриптор, но давайте сохраним это описание общего и концептуального). Запись vnode содержит почти ту же информацию, что и традиционный индекс (размер файла, другие атрибуты и т. Д.), Но также содержит другую информацию, полезную для открытых файлов, таких как блокировки файлов, которые являются активными, кто их владеет, какие части файл, который они блокируют, и т. д. Эта запись vnode также хранит указатели на блоки данных файла на диске.
Удаление файла состоит из вызова unlink(2)
. Эта функция отключает файл из каталога. Каждый файл inode на диске имеет количество ссылок, указывающих на него; файл действительно удаляется, если счетчик ссылок достигает 0 и он не открывается (или 2 в случае каталогов, поскольку каталог ссылается на себя и на который также ссылается его родитель).На самом деле, страница руководства для unlink(2)
очень специфична об этом поведении:
Unlink - удалить имя и, возможно, файл, он относится к
Таким образом, вместо того, чтобы смотреть на отменяя связи, как удаление файла, посмотрите на него как на удаление имени файла и, возможно, на файл, на который он ссылается.
Когда unlink(2)
обнаруживает, что имеется активная запись таблицы vnode, ссылающаяся на этот файл, она не удаляет файл из файловой системы. Ничего не произошло. Да, вы больше не можете найти файл в своей файловой системе. find(1)
не найдет его. Вы не можете открыть его в новых процессах.
Но файл все еще существует. Он просто не отображается ни в одной записи каталога.
Например, если это огромный файл, и если вы запустите df
или du
, вы увидите, что использование пространства - это то же самое. Файл все еще есть на диске, вы просто не можете его достичь.
Таким образом, любые чтения или записи происходят, как обычно, - блоки данных файла доступны через запись в таблице vnode. Вы все еще можете узнать размер файла. И хозяин. И разрешения. Все это. Все там.
Когда процесс завершает или явно закрывает файл, операционная система проверяет индекс. Если количество ссылок, указывающих на индексный дескриптор, равно 0, и это был последний процесс, который открыл файл (что также указывается путем сохранения количества ссылок в записи таблицы vnode), тогда файл очищается.
Я отредактировал вопрос о том, что я имел в виду под GFDT и UFDT. Чтобы объект структурного файла был чем-то уникальным только для одного процесса? я имею в виду, когда процесс закрывает файл структуры, он удаляется из его (процесса) пространства памяти, независимо от того, был ли файл удален или нет? и аналогичным образом, если файл будет удален, файл структуры не будет выполнен? – ThunderWiring