3.1.2. Links, Device Files, and Special File Types
💡 First Principle: A hard link is an additional directory entry pointing to the same inode. A symbolic link is a new inode whose data content is a path string. This single distinction explains all hard link and symlink behaviors: why hard links can't span filesystems (inodes are filesystem-local), why symlinks can point to directories (they're just a path), and why symlinks break when the target moves (they store the path, not the inode number).
# Hard links
ln /etc/hosts /etc/hosts_backup # Create hard link (same filesystem — /tmp would fail: often a separate tmpfs)
ls -li /etc/hosts /etc/hosts_backup # Same inode number confirms hard link
# Hard link constraints:
# - Cannot cross filesystem boundaries (inodes are filesystem-local)
# - Cannot link to directories (prevents directory loops)
# - Link count in ls -l shows total hard links to the inode
# Symbolic links
ln -s /etc/nginx/nginx.conf /tmp/nginx-link # Create symlink
ln -s /var/www/html /webroot # Symlink to directory
ls -la /tmp/nginx-link # Shows: nginx-link -> /etc/nginx/nginx.conf
readlink /tmp/nginx-link # Print the target path
readlink -f /tmp/nginx-link # Resolve all symlinks, print canonical path
# Broken symlink (target deleted)
ln -s /nonexistent /tmp/broken
ls -la /tmp/broken # Shows in red: broken -> /nonexistent
Hard Link vs. Symbolic Link — Decision Guide:
| Characteristic | Hard Link | Symbolic Link |
|---|---|---|
| Cross filesystem | ❌ No | ✅ Yes |
| Link to directory | ❌ No | ✅ Yes |
| Survives target move/delete | ✅ Yes (is the file) | ❌ No (path breaks) |
ls -l indicator | No arrow (looks like regular file) | -> arrow shown |
stat inode | Same as target | Different inode |
| Disk space | No extra blocks | Small (path string) |
Device Files in /dev:
ls -la /dev/sda # b rw-rw---- — block device (b prefix)
ls -la /dev/tty # c rw-rw-rw- — character device (c prefix)
ls -la /dev/null # c rw-rw-rw- — special character (discard)
ls -la /dev/zero # c rw-rw-rw- — special character (zero stream)
ls -la /dev/urandom # c rw-rw-rw- — special character (random bytes)
ls -la /dev/random # c r--r--r-- — blocks until entropy available (slower)
| Device | Type | Purpose |
|---|---|---|
/dev/sda, /dev/nvme0n1 | Block | Disk drives |
/dev/tty, /dev/pts/0 | Character | Terminals |
/dev/null | Special char | Discard all input; reads return EOF |
/dev/zero | Special char | Infinite stream of null bytes |
/dev/urandom | Special char | Non-blocking random bytes (cryptographically secure) |
/dev/random | Special char | Blocks when entropy pool is low (legacy; avoid) |
⚠️ Exam Trap: You cannot create a hard link to a directory or across filesystems — both operations fail with an error. Exam scenarios testing "which link type should be used" almost always prefer symbolic links for directories and cross-filesystem references. Use hard links only when you explicitly need the "survives target deletion" property.
Reflection Question: A web server config uses include /etc/nginx/sites-enabled/*.conf. Files in sites-enabled/ are symbolic links to files in sites-available/. A junior admin runs rm /etc/nginx/sites-available/mysite.conf to "disable" a site. Did they disable the site? What actually happened?