Frontend Labs
⋯

PHASE 2 — Linux fundamentals

You now know what the OS is doing underneath. This phase is fluency: the commands and mental models you'll use every single day, hands-on, until they stop feeling like memorisation.

Part 7 — The filesystem hierarchy and navigation

Parts 1–6 covered the OS's internals; this part and the next few turn practical. It starts with Linux's own organizing idea — that (almost) everything is a file — and the directory hierarchy that idea produces: the map you need before the command-heavy parts that follow make any sense.

Chapter 23 — Everything is a file (almost)

In one sentence

Unix's defining design choice is that files, directories, devices, pipes, and even kernel information are all accessed through the SAME simple interface — open, read, write, close — which is exactly why Linux's command-line tools compose so well together.

Why this matters

Once you internalise this, half of Linux stops looking like a pile of unrelated commands and starts looking like one consistent idea, applied everywhere.

How it actually works

   A FILE DESCRIPTOR (Chapter 2 introduced this) is just a small integer
   a process uses to refer to something it has open. Every process gets
   three, by convention, at startup:
     0   stdin    (standard input)
     1   stdout   (standard output)
     2   stderr   (standard error)
   But a file descriptor can point at FAR more than a regular file:
   a directory, a device (`/dev/sda`, your disk), a pipe (Chapter 19), a
   network socket, or a purely VIRTUAL file the kernel generates on the
   fly.

   THE VIRTUAL FILESYSTEMS ARE THE CLEAREST DEMONSTRATION of this
   philosophy taken all the way:
     /proc    a filesystem that doesn't correspond to anything on disk
             AT ALL -- it's the kernel exposing its OWN internal state
             (running processes, memory stats, CPU info) as if it were a
             directory of files, generated live, on read.
     /sys     similar idea, focused on hardware/device and kernel
             subsystem configuration.
     /dev     special files representing DEVICES -- `/dev/null` (discards
             anything written to it, always returns end-of-file when
             read), `/dev/random` (returns random bytes), `/dev/sda`
             (your actual disk, as a stream of bytes).

   THIS IS NOT JUST A CUTE ABSTRACTION -- it's WHY `ps`, `top`, and
   `free` (Chapter 31) work at all: they don't use some special, secret
   kernel API. They just READ FILES under /proc, the exact same `open`/
   `read`/`close` syscalls (Chapter 2) your own program would use to
   read a text file. You could write your own (much worse) version of
   `ps` in a few lines of shell script, entirely from `/proc`.

Real-world example

   The "everything is a file" philosophy didn't originate with Linux --
   it traces back to Unix's earliest design (Ken Thompson and Dennis
   Ritchie at Bell Labs, early 1970s) and was pushed even FURTHER by a
   later Bell Labs research OS called Plan 9, whose designers extended
   the idea to networking, graphics, and even PROCESS CONTROL, all
   exposed as file operations. Linux's `/proc` filesystem (introduced in
   the early 1990s) is a direct descendant of this same philosophy,
   deliberately choosing to expose kernel internals as a browsable,
   readable filesystem rather than inventing a separate, bespoke query
   API. The practical payoff, today, is enormous and very real: any
   tool that can read a file -- `cat`, `grep`, a shell script, a
   monitoring agent, a config-management tool -- can ALSO inspect
   process info, memory stats, or CPU details, with zero special
   libraries, because it's just text files. Countless real monitoring
   and diagnostic tools (from decades-old shell scripts to modern
   observability agents) are built on nothing more exotic than reading
   `/proc` on a schedule.

Try it yourself

# See your own process's file descriptors, live
ls -la /proc/self/fd/

# Watch `/dev/null` do exactly what it claims
echo "this vanishes" > /dev/null
cat /dev/null; echo "(nothing printed above -- always empty)"

# Read raw kernel information as plain text -- no special tool needed
cat /proc/cpuinfo | head -10
cat /proc/meminfo | head -5
cat /proc/version

# Write your OWN tiny "ps" using nothing but /proc and shell tools
for pid in /proc/[0-9]*; do
  [ -r "$pid/comm" ] && echo "$(basename $pid): $(cat $pid/comm 2>/dev/null)"
done | head -10

Build it in Go

Everything ps and top display comes from files under /proc. Chapter 79 builds a ps/top in Go from /proc/<pid>/stat, status, and cmdline, including the parsing trap where a process name contains spaces.

Common mistakes

  • Thinking /proc files are "real" files on disk. They're generated live, on read, by the kernel — there's nothing to find if you look for them on the physical disk.
  • Assuming every kernel object behaves identically to a regular file. Devices like /dev/sda can be read/written like a file, but writing the wrong bytes to the wrong offset can genuinely destroy data — this power comes with real risk.
  • Forgetting stdin/stdout/stderr ARE file descriptors 0/1/2. Redirection syntax (2>&1, >, <) is just telling the shell which file descriptor points where — not a separate, unrelated concept from everything else in this chapter.

Check yourself

  1. What does "everything is a file" actually mean, concretely?
  2. Name the three standard file descriptors every process starts with.
  3. Why can a tool like ps be implemented entirely by reading files, with no special kernel API?

(Answers: Appendix E.)

Further reading

  • Reference: man 5 proc — the exhaustive list of what's exposed under /proc.
  • Book (free): OSTEP, "Files and Directories" chapter.
  • History: search "Plan 9 everything is a file Bell Labs" for the research-OS lineage of this idea.

Generated from real-life-os-guide.md · 8 Oct 2026 16:36