IT PAPER DEEP-READ · PAPER 33
Ken Thompson & Dennis Ritchie · Bell Labs · CACM 1974
Almost everything you use today—your Mac, your iPhone, an Android phone, the Linux servers running the cloud—traces back to one small system: UNIX. Born at Bell Labs in 1969, it was first described to the world in this 1974 paper. It invented no dazzling new hardware. Instead it used a few extremely simple ideas that snap together to build an operating system small enough to fit on the cheap machines of the day, yet good enough to dominate the next half-century.
Before it, big operating systems (the flagship was Multics) tried to do everything—and ended up huge, complex, expensive, and hard to use. Worse: every kind of thing had its own special way of being used—one set of commands to read a disk, another for tape, yet another to talk to a printer. And programs couldn't easily be joined together to get work done.
UNIX's answer was "less is more," resting on just two or three moves.
Move one: everything is a file. Disk data, the keyboard, a printer, the screen—to the system they all look the same: like "a file." So one set of actions—open, read, write—operates on everything. It's like putting the same wall socket on every appliance in the house: no separate hookup to memorize for each device.
Move two: small tools plus a hose. UNIX encourages each program to do one thing and do it well, then gives you a "hose" (a pipe) that pours one program's output straight into the next program's input. To do something complex you don't write a big program—you snap small tools together like Lego, like joining hoses: "list who's logged in ┃ count the lines" counts online users in one line.
Move three: a tree of folders. Files live in folders nested inside folders, forming a tree. The nested folders you click through on your computer today came from here.
Together these moves make a system that is small, general, and able to grow new powers on its own: want a new feature? Write another small tool and snap it into a pipeline—no need to touch the system itself. That "freely combine small, orthogonal parts" style was so successful that nearly every operating system today inherits it, and the C language UNIX invented for itself became the lingua franca of programming. One honest cost: its permission model is very plain (just a few read/write flags), too coarse for today's endlessly networked world—security has had to be layered on top by later hands.
UNIX took a few minimal ideas—everything is a file, small tools freely joined by pipes, a tree of folders—and built an OS small enough for cheap hardware yet general enough to combine endlessly. Today's Linux, macOS, Android, and iOS are all its descendants in spirit.
Want the file-system diagram, the fork/pipe mechanics, and what exactly was new? → Switch to the deep read
UNIX introduced a minimal, orthogonal, freely composable operating-system design: files as unstructured byte streams, devices exposed as files (everything is a file), every program wired to a uniform "standard input/output" and joined by pipes, process creation split into fork/exec, and the whole system written in a high-level language, C. It showed that a small, carefully chosen set of fertile ideas is enough to build a small yet powerful OS—and nearly every operating system today (Linux, macOS, Android, iOS, the POSIX world) is its descendant in spirit.
The authors are Ken Thompson and Dennis Ritchie at Bell Labs. UNIX began in 1969—Thompson started writing it on an idle PDP-7; this paper, "The UNIX Time-Sharing System," appeared in CACM in 1974 and was its first public description, covering what was then the third edition. It grew out of a reaction to the sprawling Multics project (the name "UNICS" was a pun on Multics), and it seeded the entire lineage that followed—BSD, System V, Linux, macOS. Both authors received the 1983 Turing Award for it.
The big time-sharing systems of the late 1960s (Multics being the archetype) chased comprehensive functionality, at the cost of being huge, complex, expensive, and hard to use. The deeper pain was at the interface level: every class of device and every kind of file tended to have its own way of being accessed—one for disk, one for tape, one for the terminal—and programs stood isolated, so one program's output was hard to feed into another. Building something complex usually meant writing yet another big special-purpose program.
Thompson wanted the opposite: a small, comfortable, interactive system that researchers would actually use every day. The core question was—can a very small set of orthogonal primitives be composed into a system that is general, pleasant, and self-extending? The pain of the old world, in one line: big and all-encompassing, riddled with special-purpose interfaces, with parts that don't compose. Every UNIX design decision is an answer to that sentence.
UNIX defines a file with radical plainness: it is just a sequence of bytes. The system imposes no record, block, or internal structure—whether those bytes are text, an image, or a database is for the program using them to decide. This "specify nothing" step looks lazy but is the root of maximal generality: any data fits into the same container.
Files are organized in a tree of directories with a single root /, reached by path names (like /usr/dan/x) that walk from the root down to the file. The key design: a directory is itself just a kind of file, whose contents are a table mapping "name → number"; that number points to an i-node (index node), and the i-node is what actually records the file's owner, permissions, size, and data-block locations. Name and file body are thereby separated—a directory holds only names and i-node numbers; the file's substance lives elsewhere.
Why design it this way: a byte stream is maximally general (it presumes no use); the path tree extends without limit; and separating name from body lets one file carry several names (a hard link) and makes renaming and sharing nearly free.
This is UNIX's most elegant and far-sighted move: make each hardware device a special file in the file system, usually under /dev. So—writing to a terminal, sending data to a printer, storing a file on disk—all use the exact same open / read / write system calls. A program need not know whether the other end is a disk, a terminal, or a tape.
Why it matters: one interface covers all I/O in the world. A program is device-independent by birth, and its input and output can be wired by the outside to a file, a terminal, or another program—precisely the foundation for redirection and pipes below.
Open a file and what you get back is a small integer—a file descriptor. Thereafter read / write / seek all act on that integer, with no distinction between sequential and random access and buffering hidden by the system. By convention: 0 is standard input, 1 is standard output (2, standard error, was added later). A program just reads from 0 and writes to 1, and whether 0/1 connect to a keyboard, a file, or another program is something the program neither controls nor can detect—which is exactly how the shell redirects I/O with < and >.
The command interpreter, the shell, is not part of the kernel; it is an ordinary user program you can swap out at will. Because it is just a program, UNIX can upgrade the convention "each program does one thing and speaks through standard I/O" into real composition: a pipe | connects one program's standard output directly into the next program's standard input, chaining them like joined hoses. The classic who | wc -l—who lists logged-in users, wc -l counts lines—snaps two single-purpose tools together to count online users, with neither changing a line of code for the other.
How is a new process born? UNIX's answer is startlingly simple, and split into two steps. fork() copies the current process whole, yielding a child almost identical to the parent; the child then calls exec to replace its memory image with the program to run; the parent calls wait to await its end. A shell running one command is essentially fork + exec + wait; append an & and the parent doesn't wait—the job goes to the background. Why split "make a process" from "load a program"? Because in the small gap after fork and before exec, the child can calmly redirect its standard I/O and hook up pipes, then transform into the target program—redirection and pipes are implemented entirely through that gap.
At the time, operating systems were almost always written in assembly, welded to one machine. UNIX did the opposite: the whole system (most of the kernel included) is written in the high-level language C. The payoff is code that is short, readable, and easy to change—and above all, moving to a different machine requires changing only a small amount of low-level code. The authors themselves regarded this as the single most important reason for UNIX's success: for the first time an operating system could travel with the hardware, rather than be nailed to one machine.
This is not a paper that wins on benchmarks—its "result" is the running system itself. The third edition it describes ran on an ordinary PDP-11, with a resident kernel of only tens of kilobytes, yet it supported several simultaneous users time-sharing a machine with just a couple hundred kilobytes of memory, and it was put to real work at Bell Labs (notably document preparation). It made a counterintuitive point forcefully: you need neither a huge, complex system nor expensive hardware—a small set of carefully chosen, mutually orthogonal ideas can build an OS that is small, powerful, and endlessly self-extending. The harder "result" was written over the following decades—it spread with astonishing speed through universities and industry to become the shared substrate of the whole field.
Few systems papers have run deeper. Nearly every operating system today is a descendant of, or deeply shaped by, UNIX: Linux (the base of cloud computing and Android), BSD and macOS / iOS, and POSIX, which standardized this interface. More important, it left a whole vocabulary and way of thinking—file descriptors, pipes, fork, permission bits, /dev, shell scripts, tree directories, everything-is-a-file—that every programmer uses daily, most without knowing where it came from. Its "small tools, each doing one thing well, composed by pipes" philosophy became a classic paradigm of software engineering; and the C language it invented along the way went on to conquer the world. That reach is the direct reason Thompson and Ritchie won the Turing Award.
fork() as the process-creation primitive drew later criticism: in a world of many threads, large memory, and many cores, "copy whole, then replace" is both inefficient and at odds with thread semantics—a paper (A fork() in the road, 2019) bluntly called it a poor abstraction.① In one line: UNIX used a small set of minimal, orthogonal, freely composable primitives to build a small yet general time-sharing OS.
② The pain: earlier big systems (e.g. Multics) were all-encompassing, riddled with special-purpose interfaces, non-composable, and demanded expensive hardware.
③ A file = unstructured byte stream + tree of directories; a directory holds only "name → i-number," and the i-node holds the body—separating name from body gives links, cheap renames, and sharing.
④ Everything is a file: devices too are special files under /dev, sharing one open/read/write with ordinary files, so programs are device-independent by birth.
⑤ File descriptors + standard I/O (0/1/2) = the basis of redirection < > and pipes |; the shell is merely a swappable ordinary program.
⑥ Small tools chained by pipes (who | wc -l)—complexity by composition, not by writing a big program: the UNIX philosophy.
⑦ A process = fork (copy whole) + exec (replace image), split in two precisely so redirection and pipes can be set up in the gap.
⑧ The whole system written in C → portable; the authors saw this as the top reason for its success; C went on to conquer the world.
⑨ Impact: Linux / macOS / Android / iOS / POSIX all descend from it; file descriptors, pipes, fork, and the shell are common vocabulary; 1983 Turing Award.
⑩ Limits: no networking in this version; coarse permissions with setuid holes; byte streams push structure onto apps; fork criticized in modern settings; the two-sided "Worse is better."