Lesson 09 / 20
Links
The distinction between a directory entry and an inode, a hard link sharing the same inode, a symbolic link holding a path string, and a comparison of the two kinds' constraints.
Contents
The previous lesson defined deletion as “unlinking” and ended by saying a file can have more than one name. This lesson builds that possibility.
The foundation is the distinction introduced in the navigation lesson: a directory entry maps a name to an inode, while an inode holds the file’s metadata and the location of its data blocks. The name is not stored inside the inode, so nothing prevents more than one entry from pointing to the same inode.
Hard Link
A hard link is adding a new directory entry to an existing inode.
$ ln data/raw/measurement-03.csv data/latest-measurement.csv $ ls -li data/raw/measurement-03.csv data/latest-measurement.csv 22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/raw/measurement-03.csv 22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/latest-measurement.csv
Both lines show inode number 22143, and the link count column has risen from 1
to 2. This is not a copy: there is a single file with two names. No extra disk
space has been used; only a directory entry has been added.
There is no hierarchy between the two names. Which one is “real” is meaningless; both are equally close to the same inode. This shows up in deletion:
$ rm data/raw/measurement-03.csv $ ls -li data/latest-measurement.csv 22143 -rw-r--r-- 1 student student 47 Jul 26 19:03 data/latest-measurement.csv $ cat data/latest-measurement.csv zaman,sicaklik,nem 08:00,22.6,58 12:00,26.3,44
One of the names has been deleted, the link count has dropped to 1, and the data
remains in place. The rule from the previous lesson is confirmed here: data blocks
are freed only when the link count reaches zero.
The deleted name can be put back, because the inode is still reachable:
$ ln data/latest-measurement.csv data/raw/measurement-03.csv $ ls -li data/raw/measurement-03.csv data/latest-measurement.csv 22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/raw/measurement-03.csv 22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/latest-measurement.csv
Two Constraints of the Hard Link
Hard links have two constraints, and both are a direct consequence of the concept of an inode.
It cannot cross a file system boundary. An inode number is meaningful only within its own file system; an entry cannot be written to an inode on another file system.
$ ln data/raw/measurement-01.csv /dev/shm/measurement-01.csv ln: failed to create hard link '/dev/shm/measurement-01.csv' => 'data/raw/measurement-01.csv': Invalid cross-device link
This is the twin, from the same root, of the observation in the moving lesson: moving within the same file system is cheap, moving outside it turns into copying — because a directory entry can only point to inodes within its own file system.
It cannot be placed on directories.
$ ln data/raw data/raw-link ln: data/raw: hard link not allowed for directory
The prohibition exists to keep the file system a tree. If a hard link could be placed on directories, cycles could form, and any tool traversing the tree could fall into infinite recursion. The only exception to this prohibition is two entries the system itself sets up:
$ ls -lid data/. data/raw/.. 21906 drwxr-xr-x 4 student student 4096 Jul 26 19:08 data/. 21906 drwxr-xr-x 4 student student 4096 Jul 26 19:08 data/raw/..
data/. and data/raw/.. point to the same inode: both are the data directory
itself. This also explains a number left unexplained in the navigation lesson. A
directory’s link count consists of: its name in the parent directory, its own .
entry, and the .. entry of every subdirectory. Because the data directory has
two subdirectories, the number is .
Symbolic Link
A symbolic link is an entirely different object: a small file with its own inode, whose content consists of nothing but a path string. When the kernel reads this file, it goes on to resolve the path inside it.
A symbolic link suits accessing the most recent file in the measurements directory under a fixed name:
$ ln -s raw/measurement-03.csv data/current.csv $ ls -li data total 8 28322 lrwxrwxrwx 1 student student 22 Jul 26 19:08 current.csv -> raw/measurement-03.csv 21908 drwxr-xr-x 2 student student 4096 Jul 26 19:07 raw 21909 drwxr-xr-x 2 student student 4096 Jul 26 19:03 processed
The output has four details worth noting. The type character is l. The inode
number differs from the target’s — it is a separate file. The size is 22; this is
not the content of the target, but the length of the raw/measurement-03.csv string.
The permission bits appear as rwxrwxrwx and are meaningless: access control is
done according to the target’s permissions.
The target is read with readlink, while the content is accessed directly:
$ readlink data/current.csv raw/measurement-03.csv $ cat data/current.csv zaman,sicaklik,nem 08:00,22.6,58 12:00,26.3,44
Most commands follow a symbolic link: cat reads the target, not the link.
Commands that deal with the link itself (rm, mv, ls -l) do not follow it.
rm current.csv deletes the link, and does not touch the target.
Which Directory a Relative Target Is Resolved Against
The path inside a symbolic link can be relative. In that case, resolution is done not against the directory the command is run from, but against the directory the link is located in.
The link above sits inside data/ and its target is raw/measurement-03.csv;
resolution gives data/raw/measurement-03.csv. If the same link were created in a
different directory, the target could not be found:
$ ln -s data/raw/measurement-01.csv /dev/shm/measurement-01.csv $ ls -l /dev/shm/measurement-01.csv lrwxrwxrwx 1 student student 27 Jul 26 19:08 /dev/shm/measurement-01.csv -> data/raw/measurement-01.csv $ cat /dev/shm/measurement-01.csv cat: /dev/shm/measurement-01.csv: No such file or directory
The link has been created — whether the target exists is not checked — but it
cannot be resolved. There is no data/raw path inside /dev/shm. This situation
is called a dangling link.
A dangling link is not an error but the natural consequence of the definition: a symbolic link is a path string, not a handle to the target. If the target is deleted, moved, or the link is copied somewhere else, the link breaks.
The selection criterion follows from this. A relative target makes the link movable with its target: when the whole tree is copied elsewhere, the link keeps working. An absolute target points to the same file wherever the link goes, but breaks when the tree is moved. Inside a tree, a relative target is preferred; for fixed, system-wide locations, an absolute target is preferred.
Comparing the Two Kinds
| Criterion | Hard link | Symbolic link |
|---|---|---|
| What it holds | A second entry to the same inode | The target’s path string |
| Its own inode | No | Yes |
| File system boundary | Cannot cross | Can cross |
| Can be placed on a directory | No | Yes |
| When the target is deleted | Data survives, count decreases | Link breaks |
| How to tell them apart | Same number with ls -i |
l and -> in ls -l output |
The choice reduces to a simple question: is a second name needed for the same data,
or a fixed pointer to a target that can change? The first case uses a hard link, the
second a symbolic link. current.csv in the project tree is an example of the
second: when a new measurement file arrives, the link’s target changes, its name
stays fixed.
The same approach appears in system layout too. The /bin -> usr/bin link from the
directory hierarchy lesson keeps the old path working — it could not be a hard
link, since it is placed on a directory.
Summary
- A name is not a property of a file; a directory entry maps a name to an inode.
- A hard link adds a second entry to the same inode; the link count rises and there is no hierarchy among the names.
- A hard link cannot cross a file system boundary and cannot be placed on
directories;
.and..are the system’s own exceptions to this prohibition. - A symbolic link is a file with its own inode, whose content is a path string; its size is the length of the target string.
- A relative-target symbolic link is resolved against the directory the link is located in; if the target does not exist, the link is dangling, and this is a consequence of the definition, not an error.
- Inside a tree, a relative target is preferred; for fixed, system-wide locations, an absolute target is preferred.
Next Step
The project tree now contains files, copies, and links. Packaging this whole tree into a single file — to send it to another machine or to preserve a point in time — raises a separate set of problems: how are links stored, how is the directory structure converted into a flat byte sequence, and where does compression fit into this? The next lesson begins by separating archiving from compression.
To keep your progress and take notes, Log in
My notes
Log in to take notes.