Architecture
Source layers
User interface
Programs in user/ are the
visible xv6 commands and tests. They rely on the user library and
generated syscall stubs instead of linking against kernel code.
API documentation
The API index lists kernel routines, user library calls, system-call handlers, and user commands with direct links to their implementation.
Kernel boundary
trampoline.S,
trap.c, and
syscall.c
turn traps into calls to process, memory, and file-system services.
Kernel services
Process scheduling, virtual memory, files, pipes, logging, and
device drivers are linked into one supervisor-mode image and share
contracts through headers such as defs.h.
Build image
The build flow links the
kernel, links each user program, and uses
mkfs
to create the disk image mounted by the running kernel.
Runtime
User program
Code such as sh.c, cat.c, or ls.c calls functions declared in user.h.
Library and stub
ulib.c wraps helpers. usys.S, generated by usys.pl, loads a syscall number into a7 and runs ecall.
Trap and dispatch
trampoline.S and trap.c move into kernel mode. syscall.c dispatches to sysproc.c or sysfile.c.
Kernel service
Process, memory, file system, and driver code perform the request, then the return value is placed in the user trap frame.
System Calls
User programs enter the kernel through these xv6 system calls. The list follows Figure 1.2 in the xv6 guide.
| System call | Description | Implementation path |
|---|---|---|
int fork() | Create a child process and return its PID to the parent. | sys_fork in sysproc.c calls kfork in proc.c. |
int exit(int status) | Terminate the current process and report a status to wait. | sys_exit in sysproc.c calls kexit in proc.c. |
int wait(int *status) | Wait for a child process to exit and return the child's PID. | sys_wait in sysproc.c calls kwait in proc.c. |
int kill(int pid) | Mark a process so it exits when it next returns to user space. | sys_kill in sysproc.c calls kkill in proc.c. |
int getpid() | Return the current process ID. | sys_getpid in sysproc.c reads the current process through myproc. |
int pause(int n) | Pause the process for n clock ticks. | sys_pause in sysproc.c waits on timer ticks advanced by trap.c. |
int uptime() | Return the number of clock ticks since boot. | sys_uptime in sysproc.c reads timer ticks maintained by trap.c. |
int exec(char *file, char *argv[]) | Replace the current process image with a program loaded from a file. | sys_exec in sysfile.c calls kexec in exec.c. |
char *sbrk(int n) | Grow the process heap and return the previous heap end. | sys_sbrk in sysproc.c grows process memory through growproc and uvmalloc. |
int open(char *file, int flags) | Open a path and return a file descriptor. | sys_open in sysfile.c allocates file descriptors and opens inodes through namei. |
int write(int fd, char *buf, int n) | Write bytes from a user buffer to a file descriptor. | sys_write in sysfile.c calls filewrite in file.c. |
int read(int fd, char *buf, int n) | Read bytes from a file descriptor into a user buffer. | sys_read in sysfile.c calls fileread in file.c. |
int close(int fd) | Release an open file descriptor. | sys_close in sysfile.c closes descriptor references through fileclose. |
int dup(int fd) | Return another descriptor for the same open file. | sys_dup in sysfile.c duplicates descriptor references through filedup. |
int pipe(int p[]) | Create paired read and write file descriptors for a pipe. | sys_pipe in sysfile.c allocates pipe endpoints through pipealloc. |
int chdir(char *dir) | Change the current working directory. | sys_chdir in sysfile.c resolves the path through namei and updates the process directory. |
int mkdir(char *dir) | Create a directory. | sys_mkdir in sysfile.c creates a directory inode through create. |
int mknod(char *file, int, int) | Create a device file. | sys_mknod in sysfile.c creates a device inode through create. |
int fstat(int fd, struct stat *st) | Copy metadata for an open file into a user stat structure. | sys_fstat in sysfile.c calls filestat in file.c. |
int link(char *file1, char *file2) | Add another directory entry for an existing file. | sys_link in sysfile.c updates inode links and directories through dirlink. |
int unlink(char *file) | Remove a directory entry. | sys_unlink in sysfile.c resolves the parent directory through nameiparent. |
Build and Image Tools
Makefile
Builds kernel objects into kernel/kernel, builds each user program as user/_name, and packages programs into fs.img.
User binaries
User programs link with ulib.o, usys.o, printf.o, umalloc.o, and user.ld.
mkfs/mkfs.c
Creates the xv6 file system image and inserts README plus the compiled user binaries.
Kernel image
Kernel C and assembly files link with kernel.ld. QEMU boots this image directly with -kernel kernel/kernel.
QEMU devices
The Makefile attaches fs.img as a VirtIO block device and uses UART for console I/O.
User Source
Files in user/ either become runnable xv6 programs or provide the small user-space library linked into those programs. Click any file name to open a highlighted source page.
| File | Use | Relationships |
|---|---|---|
| cat.c | Prints file or standard input contents. | program Uses read, write, open, close. |
| echo.c | Writes command-line arguments to standard output. | program Uses write through printf. |
| forktest.c | Stress test for process creation limits. | test Links with a smaller library set in the Makefile. |
| grep.c | Searches input for lines matching a simple pattern. | program Uses file syscalls and user library string helpers. |
| init.c | First user process; opens the console and starts the shell. | boot userland Created by userinit through exec. |
| kill.c | Sends kill requests to process IDs. | program Calls kill. |
| ln.c | Creates hard links. | program Calls link. |
| ls.c | Lists file and directory metadata. | program Uses open, read, fstat, and stat. |
| mkdir.c | Creates directories. | program Calls mkdir. |
| rm.c | Removes directory entries. | program Calls unlink. |
| sh.c | Interactive shell with command parsing, pipes, redirection, and background jobs. | program Heavily uses fork, exec, pipe, dup, wait. |
| stressfs.c | Simple file system stress program. | test Exercises file creation, writing, reading, and process scheduling. |
| logstress.c | Stress test for logging and file-system transactions. | test Targets log.c, fs.c, and disk writes. |
| usertests.c | Main xv6 regression test suite. | test Exercises syscalls, VM, file system, pipes, and process behavior. |
| grind.c | Randomized stress test for process and file-system operations. | test Combines fork, file, pipe, and exec paths. |
| wc.c | Counts lines, words, and bytes. | program Uses file read loops and simple parsing. |
| zombie.c | Creates a zombie process for testing process state handling. | test Uses fork and exits without immediate wait. |
| forphan.c | Creates orphaned processes for process reparenting tests. | test Exercises parent exit and child cleanup. |
| dorphan.c | Directory-related orphan process test. | test Exercises process lifecycle while touching file-system paths. |
| printf.c | User-space formatted output. | library Sends formatted bytes to file descriptors with write. |
| ulib.c | Small C library: strings, memory, input, stat, and sbrk helpers. | library Linked into most user programs through ULIB. |
| umalloc.c | User-space heap allocator. | library Gets heap space through sbrk and serves malloc/free. |
| user.h | User-space declarations for syscalls and library functions. | header Included by programs and library files. |
| usys.pl | Generates assembly syscall stubs. | generator Produces usys.S, which becomes usys.o. |
| user.ld | Linker script for user programs. | linker Controls user binary layout used by exec.c. |
Kernel Source
Files in kernel/ are linked into one supervisor-mode kernel image. Headers define the shared contracts between subsystems. Click any file name to open a highlighted source page.
Boot, Traps, and System Calls
| File | Use | Relationships |
|---|---|---|
| entry.S | Earliest machine-mode entry point. | Sets up the initial stack and transfers to start.c. |
| start.c | Machine-mode setup before entering supervisor mode. | Configures timer interrupts and jumps to main.c. |
| main.c | Kernel initialization sequence. | Initializes console, memory, process table, traps, file system, devices, and scheduler. |
| kernel.ld | Kernel linker script. | Places text, data, trampoline, and kernel symbols for boot. |
| kernelvec.S | Kernel-mode trap vector assembly. | Saves registers and calls kernel trap handling in trap.c. |
| trampoline.S | Page shared by user and kernel for user trap entry/return. | Switches page tables and saves/restores user registers through trap frames. |
| trap.c | Handles traps, interrupts, and returns to user mode. | Calls syscall.c, device interrupt handlers, and scheduler yield paths. |
| syscall.c | Decodes syscall numbers and dispatches handlers. | Uses syscall.h; calls handlers in sysproc.c and sysfile.c. |
| syscall.h | Syscall number definitions. | Included by generated user stubs and kernel dispatch code. |
| sysproc.c | Process and memory syscall handlers. | Wraps proc.c, vm.c, and timer functions for user calls. |
| sysfile.c | File-system syscall handlers. | Wraps file.c, fs.c, pipe.c, and log transactions. |
Processes, Scheduling, and Memory
| File | Use | Relationships |
|---|---|---|
| proc.c | Process table, fork, exit, wait, sleep, wakeup, and scheduler. | Uses vm.c for address spaces, swtch.S for context switches, and trap.c for user return. |
| proc.h | CPU, process, context, and trapframe structures. | Included by process, trap, syscall, and VM code. |
| swtch.S | Low-level context switch routine. | Saves and restores kernel registers for scheduler switches. |
| vm.c | Kernel and user virtual memory management. | Maps pages, copies user memory, handles page faults, and works with kalloc.c. |
| vm.h | Page-table type aliases and helpers. | Shared by VM and process code. |
| kalloc.c | Physical page allocator. | Supplies pages for page tables, user memory, kernel stacks, and buffers. |
| memlayout.h | Physical and virtual memory layout constants. | Used by boot, VM, device, and trap code. |
| riscv.h | RISC-V registers, page-table flags, and inline assembly helpers. | Used throughout low-level kernel code. |
File System, Files, Pipes, and Exec
| File | Use | Relationships |
|---|---|---|
| exec.c | Loads ELF user programs into a process address space. | Reads inodes through fs.c, builds user memory with vm.c, and uses elf.h. |
| elf.h | ELF executable format structures. | Used by exec.c to parse user binaries. |
| file.c | Open file table and file descriptor operations. | Connects syscalls to inodes, pipes, and device files. |
| file.h | Open file, inode, and device switch structures. | Shared by file, fs, pipe, and syscall code. |
| fcntl.h | Open flag constants. | Shared with user programs through includes. |
| fs.c | Inode, directory, block mapping, and path-name logic. | Uses buffer cache, log, and disk blocks; called by file and exec code. |
| fs.h | On-disk file-system layout structures. | Shared with mkfs/mkfs.c so images match the kernel format. |
| bio.c | Buffer cache for disk blocks. | Uses virtio_disk.c for actual I/O and is used by fs/log code. |
| buf.h | Buffer cache structure definition. | Shared by bio, log, fs, and disk driver code. |
| log.c | Simple write-ahead log for file-system updates. | Coordinates transactional writes from file-system syscalls. |
| pipe.c | Kernel pipe implementation. | Provides file-like read/write endpoints for pipe syscalls. |
| stat.h | File metadata structure. | Shared with user space for fstat and stat. |
Devices, Locks, and Utilities
| File | Use | Relationships |
|---|---|---|
| console.c | Console input/output device. | Uses UART, provides consoleread/consolewrite through the device switch. |
| uart.c | UART serial driver. | Backs console output/input and handles UART interrupts. |
| plic.c | Platform-Level Interrupt Controller setup. | Routes external interrupts from UART and VirtIO to trap handling. |
| virtio_disk.c | VirtIO block device driver. | Reads and writes disk blocks for the buffer cache. |
| virtio.h | VirtIO MMIO and descriptor definitions. | Used by virtio_disk.c. |
| spinlock.c | Spinlock implementation for short critical sections. | Used across process, buffer, file, device, and memory code. |
| spinlock.h | Spinlock structure definition. | Included by code that embeds or manipulates spinlocks. |
| sleeplock.c | Sleepable locks for longer disk/inode operations. | Used mainly by inode and buffer-related file-system paths. |
| sleeplock.h | Sleeplock structure definition. | Included by file-system structures. |
| printf.c | Kernel formatted printing and panic. | Outputs through console/UART and supports diagnostics. |
| string.c | Kernel string and memory routines. | Used by many kernel subsystems because the kernel is freestanding. |
| defs.h | Cross-file kernel function declarations. | Main internal API header connecting kernel subsystems. |
| types.h | Basic integer and page-table types. | Included broadly by both kernel and user-facing headers. |
| param.h | Kernel size limits and constants. | Defines limits such as process count, file counts, and log size. |