Inode

Жесткая ссылка – не копия!

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

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

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

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

Implications

  • Files can have multiple names. If multiple names hard link to the same inode then the names are equivalent; i.e., the first to be created has no special status. This is unlike symbolic links, which depend on the original name, not the inode (number).
  • An inode may have no links. An unlinked file is removed from disk, and its resources are freed for reallocation but deletion must wait until all processes that have opened it finish accessing it. This includes executable files which are implicitly held open by the processes executing them.
  • It is typically not possible to map from an open file to the filename that was used to open it. The operating system immediately converts the filename to an inode number then discards the filename. This means that the getcwd() and getwd() library functions search the parent directory to find a file with an inode matching the working directory, then search that directory’s parent, and so on until reaching the root directory. SVR4 and Linux systems maintain extra information to make this possible.
  • Historically, it was possible to hard link directories. This made the directory structure into an arbitrary directed graph contrary to a directed acyclic graph. It was even possible for a directory to be its own parent. Modern systems generally prohibit this confusing state, except that the parent of root is still defined as root. The most notable exception to this prohibition is found in Mac OS X (versions 10.5 and higher) which allows hard links of directories to be created by the superuser.
  • A file’s inode number stays the same when it is moved to another directory on the same device, or when the disk is defragmented which may change its physical location. This also implies that completely conforming inode behavior is impossible to implement with many non-Unix file systems, such as FAT and its descendants, which don’t have a way of storing this invariance when both a file’s directory entry and its data are moved around.
  • Installation of new libraries is simple with inode file systems. A running process can access a library file while another process replaces that file, creating a new inode, and an all-new mapping will exist for the new file so that subsequent attempts to access the library get the new version. This facility eliminates the need to reboot to replace currently mapped libraries.
  • It is possible for a device to run out of inodes. When this happens, new files cannot be created on the device, even though there may be free space available. This is most common for use cases like mail servers which contain many small files. File systems (such as JFS or XFS) escape this limitation with extents or dynamic inode allocation, which can «grow» the file system or increase the number of inodes.

«ls -i» lists the inode of a file

Normal Unix/Linux/MacOS users aren’t even aware that inodes exist. But there’s an easy way to discover them — using the «ls -i» command. Let’s look at the root file system:

% cd /
% ls -i
2637825 bin     983041 etc	       1572865 lib	   2981889 media  2531329 root	 106497 selinux    81921 usr
 196609 boot         2 home	       1761281 lib64	   2129921 mnt	     6416 run	2457601 srv	  425985 var
% ls -lai | tail -7
total 132
      2 drwxr-xr-x  24 root root   4096 Feb 26 13:31 .
      2 drwxr-xr-x  24 root root   4096 Feb 26 13:31 ..
2637825 drwxr-xr-x   2 root root   4096 Jan 14 19:02 bin
 196609 drwxr-xr-x   3 root root   4096 Feb 24 10:41 boot
      3 drwxr-xr-x  16 root root   4460 Mar  5 09:35 dev
 983041 drwxr-xr-x 206 root root  12288 Mar  5 07:45 etc
      2 drwxr-xr-x  14 root root   4096 Dec 29 09:24 home

That’s interesting — three of the files have the inode value of «2».
But as you shall see, this makes perfect sense.

As Unix systems can support many different types of file systems,
in the

filesystem, inode #2 is always the root file system. If you want to
look for a file, you start with inode #2 and work down into the
directory structure.
Normally the «..» directory points to the parent directory, but since «/» is the top of the tree, the parent of «/» is «/».

The «dev» directory has the inode «3». I suspect that when the filesystem was created, the «/dev» directory was the first file to be created.

But, you may wonder, why does «home» have the inode of «2»? You have sharp eyes.

The reason is simple. It happens to be a different partition, and «/home» is the root of that partition.

Inodes are always unique, but unique per partition. To uniquely identify a file, you need the inode and the device (the disk partition).

Значение

Файловые системы, использующие индексные дескрипторы, имеют несколько неочевидных особенностей:

  • Если несколько имен указывают на один и тот же индексный дескриптор (жёсткие ссылки), то все имена считаются эквивалентными. Первое созданное имя никаким особым положением не обладает. Это отличается от поведения похожих символьных ссылок, которые зависят от первоначального имени.
  • Индексный дескриптор может совсем не иметь ссылок. Обычно такой файл должен быть удален с диска (именно поэтому программы типа undelete в Unix не позволяют установить точное имя удалённого файла), а его ресурсы должны освободиться (это нормальный процесс удаления файла), но если какие-либо процессы ещё не закрыли файл, то они могут удерживать доступ к нему, а файл будет окончательно удален только после того, как будет закрыто последнее обращение к нему. Это относится и к исполняемым копиям, которые удерживаются открытыми процессами, их выполняющими. По этой причине при обновлении программы рекомендуется удалять старую копию и создавать новый индексный дескриптор для обновлённой версии, чтобы никакие экземпляры старой версии не продолжали выполняться.
  • Обычно нет возможности сопоставить открытый файл и его имя, по которому он был открыт. Операционная система преобразует имя файла в номер индексного дескриптора при первом же удобном случае, а затем «забывает» про использованное имя файла. Таким образом, функции библиотек <tt>getcwd()</tt> и <tt>getwd()</tt> начинают искать в родительском каталоге файл с индексным дескриптором, совпадающим с файлом «.» каталога; затем ищут родительский каталог для текущего, и так далее пока не достигнут «» каталога. и Linux используют дополнительную информацию (поля) в индексных дескрипторах для избежания подобного неудобства.
  • Ранее было возможно применять жёсткие ссылки на каталоги. Это делало структуру каталогов ориентированным графом вместо дерева (то есть связного графа с N-1 ребрами и N узлами). Например, каталог имел возможность быть собственным родителем. Современные файловые системы не допускают подобных двусмысленностей, за исключением корневого каталога, который считается собственным родителем.
  • Номер индексного дескриптора файла остается неизменным при перемещении файла в другой каталог на том же устройстве или при дефрагментации диска. Поэтому перемещения или каталога, содержащего файл, или его содержимого (или и того и другого вместе) недостаточно для предотвращения доступа к нему из уже запущенного процесса, если у процесса есть возможность вычислить номер индексного дескриптора. Это также обусловливает то, что полностью управляемое поведение индексных дескрипторов невозможно реализовать на множестве файловых систем, не произошедших от стандартной файловой системы UNIX, таких как FAT и его преемников, которые не имеют возможности хранить подобную постоянную ‘неизменность’, когда каталог файла и его содержимое перемещается.

Значение

Файловые системы, использующие индексные дескрипторы, имеют несколько неочевидных особенностей:

  • Если несколько имен указывают на один и тот же индексный дескриптор (жёсткие ссылки), то все имена считаются эквивалентными. Первое созданное имя никаким особым положением не обладает. Это отличается от поведения похожих символьных ссылок, которые зависят от первоначального имени.
  • Индексный дескриптор может совсем не иметь ссылок. Обычно такой файл должен быть удален с диска (именно поэтому программы типа undelete в Unix не позволяют установить точное имя удалённого файла), а его ресурсы должны освободиться (это нормальный процесс удаления файла), но если какие-либо процессы ещё не закрыли файл, то они могут удерживать доступ к нему, а файл будет окончательно удален только после того, как будет закрыто последнее обращение к нему. Это относится и к исполняемым копиям, которые удерживаются открытыми процессами, их выполняющими. По этой причине при обновлении программы рекомендуется удалять старую копию и создавать новый индексный дескриптор для обновленной версии, чтобы никакие экземпляры старой версии не продолжали выполняться.
  • Обычно нет возможности сопоставить открытый файл и его имя, по которому он был открыт. Операционная система преобразует имя файла в номер индексного дескриптора при первом же удобном случае, а затем «забывает» про использованное имя файла. Таким образом, функции библиотек getcwd() и getwd() начинают искать в родительском каталоге файл с индексным дескриптором, совпадающим с файлом «.» каталога; затем ищут родительский каталог для текущего, и так далее пока не достигнут «» каталога. и Linux используют дополнительную информацию (поля) в индексных дескрипторах для избежания подобного неудобства.
  • Ранее было возможно применять жёсткие ссылки на каталоги. Это делало структуру каталогов ориентированным графом вместо дерева (то есть связного графа с N-1 ребрами и N узлами). Например, каталог имел возможность быть собственным родителем. Современные файловые системы не допускают подобных двусмысленностей, за исключением корневого каталога, который считается собственным родителем.
  • Номер индексного дескриптора файла остается неизменным при перемещении файла в другой каталог на том же устройстве или при дефрагментации диска. Поэтому перемещения или каталога, содержащего файл, или его содержимого (или и того и другого вместе) недостаточно для предотвращения доступа к нему из уже запущенного процесса, если у процесса есть возможность вычислить номер индексного дескриптора. Это также обусловливает то, что полностью управляемое поведение индексных дескрипторов невозможно реализовать на множестве файловых систем, не произошедших от стандартной файловой системы UNIX, таких как FAT и его преемников, которые не имеют возможности хранить подобную постоянную ‘неизменность’, когда каталог файла и его содержимое перемещается.
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector