/..
points to /
:
$ ls -id /
2 /
$ ls -id /..
2 /..
Both have the same inode number, which happens to be 2 on this system. (The exact value doesn't matter.)
It's done for consistency. This way, there doesn't have to be code in the kernel to check where it currently is when it processes a ..
in a path. You can say cd ..
forever, and never go deeper than the root.
An interesting question, indeed. At first glance I see the following advantages:
First of all you state that interpreting ".
" as the current directory may be done by the Shell or by system calls. But having the dot-entry in the directory actually removes this necessity and forces consistency at even a lower level.
But I don't think that this was the basic idea behind this design decision.
When a file is being created or removed from a directory, the directory's modification time stamp has to be updated, too. This timestamp is stored in its inode. The inode number is stored in the corresponding directory entry.
IF the dot entry would not be there, the routines would have to search for the inode number at the entry for this directory in the parent directory, which would cause a directory search again.
BUT luckily there is the dot entry in the current directory. The routine that adds or removes a file in the current directory just has to jump back to the first entry (where the dot-entry usually resides) and immediately has found the inode number for the current directory.
There is a third nice thing about the dot entry:
When fsck
checks a rotten filesystem and has to deal with non-connected blocks that are also not on the free list, it's easy for it to verify if a data block (when interpreted as a directory list) has a dot entry that's pointing to an inode which in turn points back to this data block. If so, this data block may be considered as a lost directory which has to be reconnected.
Best Answer
Historically, the first Unix filesystem created two entries in every directory:
.
pointing to the directory itself, and..
pointing to its parent. This provided an easy way to traverse the filesystem, both for applications and for the OS itself.Thus each directory has a link count of 2+n where n is the number of subdirectories. The links are the entry for that directory in its parent, the directory's own
.
entry, and the..
entry in each subdirectory. For example, suppose this is the content of the subtree rooted at/parent
, all directories:Then
dir
has a link count of 5: thedir
entry in/parent
, the.
entry in/parent/dir
, and the three..
entries in each of/parent/dir/sub1
,/parent/dir/sub2
and/parent/dir/sub3
. Since/parent/dir/sub1
has no subdirectory, its link count is 2 (thesub1
entry in/parent/dir
and the.
entry in/parent/dir/sub1
).To minimize the amount of special-casing for the root directory, which doesn't have a “proper” parent, the root directory contains a
..
entry pointing to itself. This way it, too, has a link count of 2 plus the number of subdirectories, the 2 being/.
and/..
.Later filesystems have tended to keep track of parent directories in memory and usually don't need
.
and..
to exist as actual entries; typical modern unix systems treat.
and..
as special values as part of the filesystem-type-independent filesystem code. Some filesystems still include.
and..
entries, or pretend to even though nothing appears on the disk.Most filesystems still report a link count of 2+n for directories regardless of whether
.
and..
entries exist, but there are exceptions, for example btrfs doesn't do this.