Skip to content
ALB Wiki

Filesystem

This is an old revision of this page — revision 2 (1970-01-21 18:02:21 UTC). It may differ from the current revision.

Linux's filesystem is one tree — a single root / from which every disk, every device, every process, every kernel interface hangs. There are no drive letters; a second disk doesn't become D: — it mounts into the tree at any point you choose. And beneath the tree: inodes — the kernel's real file objects, which filenames merely point at. Learn the tree and the inodes and you've learned the filesystem; everything else is elaboration.

The one-tree rule

A disk, a CD-ROM, a USB stick, a network share, a directory of the kernel's internals — all appear as paths under /. The filesystem namespace is unified even though the storage behind it is scattered across devices:

df -hT          # which device backs which path — the tree's true plumbing
mount           # every currently-mounted filesystem
findmnt         # the mount tree, visualized

This is what mount actually does — graft a device onto a path. Unmount it and the path is empty again; the tree is the interface, the mounts are the plumbing.

The FHS map

The Filesystem Hierarchy Standard names every top-level directory:

PathHoldsNotes
/binessential user binaries→ /usr/bin (merged-usr on modern systems)
/bootkernel, initramfs, bootloaderoften its own partition
/devdevice filesdevtmpfs — populated by the kernel itself
/etcsystem configurationall text, all yours
/homeuser homes
/libessential shared libraries→ /usr/lib
/mediaauto-mount point for removable media
/mntmanual temporary mountsLFS's staging ground
/optthird-party software
/procprocess + kernel statevirtual — kernel-composed, not on disk
/rootroot's home
/runruntime statetmpfs — dies on boot
/sbinsystem binaries→ /usr/sbin
/srvsite-served data
/sysdevices/drivers/kernel objectssysfs — virtual
/tmptemporary filesusually tmpfs; world-writable + sticky
/usrthe userland's bulkbin, lib, share — read-only-able
/varvariable datalogs, spool, caches

The modern merged-usr layout makes /bin, /sbin, /lib symlinks into /usr — the split is historical (early / was a rescue root; /usr came later); modern systems unify them.

Inodes — what a file actually is

A filename is not a file — it's a directory entry pointing at an inode. The inode holds everything: size, owner, permissions, timestamps, and the block pointers to the data. The name is just one of possibly several links to it:

ls -i file            # the inode number
stat file             # the inode's full record: times, links, blocks
df -i                 # inode exhaustion — a full FS can have blocks free

This architecture explains three Unix truths:

  • Hard links — ln a b makes a second name for the same inode; no "original" exists, only a refcount. Delete one name and the file persists until the last name goes.
  • Symlinks — ln -s makes a new inode whose contents are a path — a pointer by name, not by number; it dangles if the target dies.
  • Moving within a filesystem is free — mv rewrites a directory entry; the inode and data never move. mv across filesystems is copy+delete.

The FHS map — the deep version

PathHoldsNotes
/bin →/usr/binuser binariesls cp mv bash — merged-usr symlink
/bootkernel + initramfs + bootloaderits own partition often; vmlinuz-* initrd grub/
/devdevice nodesdevtmpfs — kernel-populated: null zero urandom tty sda* pts/
/etcall configurationfstab passwd shadow ssh/ sysconfig/ hosts resolv.conf
/homeuser homes~alice etc
/lib →/usr/libshared libslibc.so the ld.so linker
/lib6464-bit libsx86_64 split
/mediaautomount pointCDs, USB sticks
/mntmanual mountsLFS's $LFS
/optthird-partyself-contained packages
/prockernel+process statevirtual — cpuinfo meminfo PID/
/rootroot's home
/runruntime statetmpfs — run/user/ run/lock
/sbin →/usr/sbinadmin binariesfdisk mkfs useradd init
/srvsite-served data
/sysdevice/driver objectssysfs — class/ block/ bus/
/tmptempworld-writable sticky 1777, cleared on boot
/usrthe userland bulkbin lib share include local src — can be read-only
/usr/localyour additionssoftware you installed yourself
/varvariable datalog spool cache mail lib
/var/logthe logsmessages syslog auth.log
/var/libstatedpkg status, rpm db
/var/spoolqueuesmail, cron, printing

The merged-usr story: historically / was a minimal rescue root; /usr came later with the real userland — modern systems merge /bin /sbin /lib → /usr/* symlinks. The FHS exists so every Linux looks the same — a file lives where you expect.

The special file types — the complete set

ls -l
-   regular file
d   directory
l   symlink — a path in an inode
c   character device — streams: tty, null, urandom, serial
b   block device — random-access: sda, loop
p   named pipe — FIFO — mkfifo
s   unix socket — local IPC

mkfifo myfifo; echo hi > myfifo & cat myfifo   # a file that's a queue
mknod /dev/foo b 8 32                          # a device node by hand

Devices as files

/dev holds not programs but device nodes — files that open kernel drivers:

ls -l /dev | head
# crw-rw-rw- 1 root root 1, 3 null    <- c = character, 1,3 = major,minor
# brw-rw---- 1 root disk 8, 0 sda    <- b = block device
echo hi > /dev/null                 # a write to the kernel's void
cat /dev/urandom | head -c16 | xxd  # reading entropy as a file

Major number = which driver; minor = which instance. /dev/null, /dev/zero, /dev/urandom, /dev/full, tty devices, disks — all files, all opened with the same open() syscall. This is "everything is a file" made literal.

Virtual filesystems — the kernel exposes itself

Three pseudo-filesystems are kernel interfaces wearing file costumes:

  • /proc — every process as a directory; kernel state as files: cat /proc/cpuinfo, cat /proc/meminfo, ls /proc/self, echo 1 > /proc/sys/net/ipv4/ip_forward to configure the kernel by writing a file.
  • /sys (sysfs) — devices, drivers, buses as a browsable object tree.
  • /dev (devtmpfs) — populated automatically as hardware is detected.

None of it lives on disk — the kernel composes it on read. It's the purest "everything is a file" — including the kernel's own mind.

Filesystem types

FSPurpose
ext4The boring correct default — journaled, everywhere
xfsLarge files, large filesystems
btrfsCoW, snapshots, checksums
tmpfsRAM-backed — /run, /tmp
vfatThe ESP, USB sticks, interop
iso9660CD images
nfs, cifsNetwork filesystems
proc, sysfs, devtmpfs, cgroup2The kernel interfaces

Permissions on the tree

Every inode carries owner, group, and mode — the rwxrwxrwx triad ×3 (detailed in Users and permissions). On filesystems: mount options like noexec, nosuid, nodev, ro constrain what inodes permit — /proc and /sys mount nosuid,nodev,noexec for good reason.

/proc — the kernel's process window, deeper

cat /proc/cpuinfo          # every core's model, flags, mhz
cat /proc/meminfo          # the memory ledger — MemFree vs Buffers/Cached
cat /proc/loadavg          # load averages + running/total + last pid
cat /proc/uptime           # uptime + idle seconds
cat /proc/mounts           # the real mount table
cat /proc/filesystems      # what filesystems the kernel knows
cat /proc/partitions       # the block devices
cat /proc/version          # kernel + compiler
cat /proc/cmdline          # the boot params
cat /proc/interrupts       # irq traffic
cat /proc/net/tcp          # the sockets, raw
cat /proc/sys/kernel/hostname   # a writable kernel knob
ls /proc/self/             # YOUR reading process as files

Every process is /proc/PID/ — status, cmdline, environ, fd/, maps, io, limits, cwd→real path, exe→the binary. /proc/sys/ is the sysctl tree — writable knobs. /proc is pure kernel-composed — cat runs code, not disk I/O.

/sys — the device object tree

ls /sys/class/net/              # every NIC as a directory
cat /sys/class/net/eth0/address # its MAC
ls /sys/block/                  # every block device
cat /sys/block/sda/queue/scheduler  # io scheduler — live-tunable
ls /sys/bus/usb/devices/        # the USB tree
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo performance > /sys/.../scaling_governor   # tune it
udevadm info -a /dev/sda        # the device's full sysfs record

/sys is sysfs — the kernel's devices, drivers, buses, and classes as a browsable hierarchy — the same objects udev watches for hotplug.

Mount options — the flags that harden

mount -o ro,noexec,nosuid,nodev /dev/sda3 /mnt
# ro       read-only
# noexec   no binaries execute — /tmp, data partitions
# nosuid   setuid bits disabled
# nodev    no device files honored
# noatime  don't update access times — the performance flag
# relatime the modern atime compromise (default)
# sync     no write caching
# _netdev  wait for network
# nofail   don't fail boot if absent
# x-systemd.automount   lazy-mount on first access
# bind     mount a dir onto another path

noexec/nosuid/nodev/ro on /tmp, /proc, /sys, data mounts are the hardening layer the fstab options encode.

The file types — the leading char decoded

ls -l
# - regular file
# d directory
# l symlink
# c character device — streams (tty, null)
# b block device — random access (disks)
# p named pipe — FIFO
# s unix socket
mkfifo myfifo               # a named pipe — a file that's a queue

Practical: find and friends

find /etc -name '*.conf'            # name match
find / -type f -size +100M 2>/dev/null   # the space hogs
find . -mtime -7                    # changed this week
find / -xdev -name target           # stay on one filesystem
find . -type l -xtype l             # broken symlinks
du -sh /var/* | sort -rh | head     # where the space went

Exercises

  1. findmnt — draw the actual mount tree of your system.
  2. Create a hard link and a symlink; stat both; explain the inode difference.
  3. cat /proc/meminfo, ls /sys/class/net — browse the kernel's mind.
  4. df -i — could your filesystem hold a million empty files?
  5. Mount a USB stick manually — mount /dev/sdX1 /mnt — and unmount.

Timeline

ConceptWhat it is
One treeEvery device grafts into /
InodesThe real files; names are links
/devDevices as files
/proc, /sysThe kernel exposing itself
FHSThe standard map of /

See also

This page was last edited 1970-01-21 18:02:21 UTC by Devin. What links here