xv6
a simple, Unix-like teaching operating system
Russ Cox
Frans Kaashoek
Robert Morris
xv6-book@pdos.csail.mit.edu
Draft as of August 29, 2017
Contents
0 Operating system interfaces
1 Operating system organization
2 Page tables
3 Traps, interrupts, and drivers
4 Locking
5
Scheduling
6 File system
7
Summary
A PC hardware
B The boot loader
Index
7
17
29
39
51
61
77
93
95
99
105
DRAFT as of August 29, 2017
3
https://pdos.csail.mit.edu/6.828/xv6
Foreword and acknowledgements
This is a draft text intended for a class on operating systems. It explains the main con-
cepts of operating systems by studying an example kernel, named xv6. xv6 is a re-im-
plementation of Dennis Ritchie’s and Ken Thompson’s Unix Version 6 (v6). xv6 loose-
ly follows the structure and style of v6, but is implemented in ANSI C for an x86-
based multiprocessor.
The text should be read along with the source code for xv6. This approach is inspired
by John Lions’s Commentary on UNIX 6th Edition (Peer to Peer Communications; IS-
BN: 1-57398-013-7; 1st edition (June 14, 2000)). See https://pdos.csail.mit.edu/6.828 for
pointers to on-line resources for v6 and xv6.
We have used this text in 6.828, the operating systems class at MIT. We thank the fac-
ulty, teaching assistants, and students of 6.828 who have all directly or indirectly con-
tributed to xv6. In particular, we would like to thank Austin Clements and Nickolai
Zeldovich. Finally, we would like to thank people who emailed us bugs in the text:
Abutalib Aghayev, Sebastian Boehm, Anton Burtsev, Raphael Carvalho, Color Fuzzy,
Giuseppe, Wolfgang Keller, Austin Liew, Pavan Maddamsetti, Jacek Masiulaniec, Askar
Safin, Salman Shah, Pawel Szczurko, Warren Toomey, and Zou Chang Wei.
If you spot errors or have suggestions for improvement, please send email to Frans
Kaashoek and Robert Morris (kaashoek,rtm@csail.mit.edu).
DRAFT as of August 29, 2017
5
https://pdos.csail.mit.edu/6.828/xv6
Chapter 0
Operating system interfaces
interface design
kernel
process
system call
user space
kernel space
The job of an operating system is to share a computer among multiple programs
and to provide a more useful set of services than the hardware alone supports. The
operating system manages and abstracts the low-level hardware, so that, for example, a
word processor need not concern itself with which type of disk hardware is being
used. It also shares the hardware among multiple programs so that they run (or ap-
pear to run) at the same time. Finally, operating systems provide controlled ways for
programs to interact, so that they can share data or work together.
An operating system provides services to user programs through an interface.
Designing a good interface turns out to be difficult. On the one hand, we would like
the interface to be simple and narrow because that makes it easier to get the imple-
mentation right. On the other hand, we may be tempted to offer many sophisticated
features to applications. The trick in resolving this tension is to design interfaces that
rely on a few mechanisms that can be combined to provide much generality.
This book uses a single operating system as a concrete example to illustrate oper-
ating system concepts. That operating system, xv6, provides the basic interfaces intro-
duced by Ken Thompson and Dennis Ritchie’s Unix operating system, as well as mim-
icking Unix’s internal design. Unix provides a narrow interface whose mechanisms
combine well, offering a surprising degree of generality. This interface has been so
successful that modern operating systems—BSD, Linux, Mac OS X, Solaris, and even,
to a lesser extent, Microsoft Windows—have Unix-like interfaces. Understanding xv6
is a good start toward understanding any of these systems and many others.
As shown in Figure 0-1, xv6 takes the traditional form of a kernel, a special pro-
gram that provides services to running programs. Each running program, called a
process, has memory containing instructions, data, and a stack. The instructions im-
plement the program’s computation. The data are the variables on which the computa-
tion acts. The stack organizes the program’s procedure calls.
When a process needs to invoke a kernel service, it invokes a procedure call in
the operating system interface. Such a procedure is called a system call. The system
call enters the kernel; the kernel performs the service and returns. Thus a process al-
ternates between executing in user space and kernel space.
The kernel uses the CPU’s hardware protection mechanisms to ensure that each
process executing in user space can access only its own memory. The kernel executes
with the hardware privileges required to implement these protections; user programs
execute without those privileges. When a user program invokes a system call, the
hardware raises the privilege level and starts executing a pre-arranged function in the
kernel.
The collection of system calls that a kernel provides is the interface that user pro-
grams see. The xv6 kernel provides a subset of the services and system calls that Unix
kernels traditionally offer. Figure 0-2 lists all of xv6’s system calls.
DRAFT as of August 29, 2017
7
https://pdos.csail.mit.edu/6.828/xv6
user
space
kernel
space
shell
cat
system
call
Kernel
Figure 0-1. A kernel and two user processes.
process
The rest of this chapter outlines xv6’s services—processes, memory, file descrip-
tors, pipes, and file system—and illustrates them with code snippets and discussions of
how the shell, which is the primary user interface to traditional Unix-like systems,
uses them. The shell’s use of system calls illustrates how carefully they have been de-
signed.
The shell is an ordinary program that reads commands from the user and exe-
cutes them. The fact that the shell is a user program, not part of the kernel, illustrates
the power of the system call interface: there is nothing special about the shell. It also
means that the shell is easy to replace; as a result, modern Unix systems have a variety
of shells to choose from, each with its own user interface and scripting features. The
xv6 shell is a simple implementation of the essence of the Unix Bourne shell. Its im-
plementation can be found at line (8550).
shell
time-share
pid+code
fork+code
child process
parent process
fork+code
exit+code
Processes and memory
An xv6 process consists of user-space memory (instructions, data, and stack) and
per-process state private to the kernel. Xv6 can time-share processes: it transparently
switches the available CPUs among the set of processes waiting to execute. When a
process is not executing, xv6 saves its CPU registers, restoring them when it next runs
the process. The kernel associates a process identifier, or pid, with each process.
A process may create a new process using the fork system call. Fork creates a
new process, called the child process, with exactly the same memory contents as the
calling process, called the parent process. Fork returns in both the parent and the
child. In the parent, fork returns the child’s pid; in the child, it returns zero. For ex-
ample, consider the following program fragment:
int pid = fork();
if(pid > 0){
printf("parent: child=%d\n", pid);
pid = wait();
printf("child %d is done\n", pid);
} else if(pid == 0){
printf("child: exiting\n");
exit();
} else {
printf("fork error\n");
}
The exit system call causes the calling process to stop executing and to release re-
DRAFT as of August 29, 2017
8
https://pdos.csail.mit.edu/6.828/xv6