Introduction to xv6
What the cat is xv6?
xv6 is a simple Unix-like educational (aka. toy) operating system developed by MIT. It was designed to help you understand how modern operating systems work.
xv6 File Structure
Kernel:
| File / Directory | Description |
|---|---|
kernel/ | Contains all kernel source code |
kernel/defs.h | Global function declarations |
kernel/proc.c | Process creation, scheduling, and switching |
kernel/syscall.c | System call dispatch table |
kernel/trap.c | Interrupt and exception handling |
kernel/fs.c | File system implementation |
kernel/vm.c | Page table and virtual memory management |
kernel/exec.c | Handles execution of new programs (exec) |
kernel/sysproc.c | Implementation of process-related system calls |
kernel/syscall.h | System call number definitions |
kernel/param.h | Defines global system parameters and limits (e.g., max processes, open files, path length). |
User:
| File / Directory | Description |
|---|---|
user/ | Contains user-level programs (ls, sh, cat, etc.) |
user/user.h | Declarations for user-space functions |
user/usys.pl | Perl script that generates system call stubs (usys.S) for user programs |
user/init.c | First user program that runs after boot |
user/echo.c, user/ls.c, etc. | Built-in user programs |
Other Important Files:
| File / Directory | Description |
|---|---|
Makefile | Main build configuration |
mkfs/mkfs.c | Tool for building xv6 filesystem image |
README | Official documentation |
Some Basic Operations
How to run xv6?
You can run xv6 by typing make qemu in the terminal.
$ make qemuYou might need to use the following commands.
| Command | Description |
|---|---|
make clean | Removes compiled files. |
make | Compiles xv6 and builds the disk image (no execution). |
make qemu | Builds xv6 and runs it inside QEMU. |
make qemu-gdb | Runs xv6 and waits for a GDB connection — useful for kernel debugging. |
How to exit xv6?
You can exit xv6 by pressing Ctrl-A and X.
How to add a new system call?
Suppose we want to add a new system call First, add a function prototype: Then, register it in the syscalls array: And you can call this system call by mycall() in user program.mycall()1. Declare a new syscall number in
kernel/syscall.h:// ... other syscalls
#define SYS_fork 1
#define SYS_exit 2
...
#define SYS_close 21
#define SYS_mycall 22 // <-- Add your syscall here2. Register the syscall in
kernel/syscall.c:// ...
extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
extern uint64 sys_mycall(void); // <-- Add this linestatic uint64 (*syscalls[])(void) = {
[SYS_fork] sys_fork,
[SYS_exit] sys_exit,
// ...
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_mycall] sys_mycall, // <-- Add this line
};3. Implement the syscall in
kernel/sysproc.c:...
uint64
sys_mycall(void)
{
printf("Hello from the kernel!\n");
return 0;
}4. Add the user-space stub in
user/usys.pl:...
entry("uptime");
entry("mycall"); # <-- Add this line5. Add the user-space API in
user/user.h:...
int uptime(void);
int mycall(void); // <-- Add this line
How to add a new user program?
Suppose we want to add a new user program called hello. Create a new file named Once xv6 starts, type the following in the xv6 shell: You should see:1. Create a new file in the
user/:hello.c in the user/ directory:#include "kernel/types.h"
#include "kernel/stat.h"
#include "user.h"
int main(int argc, char *argv[]) {
printf("hello! your name is %s\n",argv[1]);
exit(0);
} 2. Add the program to the UPROGS list in the
Makefile:UPROGS=\
$U/_cat\
$U/_echo\
$U/_grep\
...
$U/_hello\ <----- <-- Add this line
...3. Rebuild and run xv6
$ make clean
$ make qemu4. Run program
$ hello amyhello! your name is amy
Modify parameters
1. Edit kernel/param.h:
System parameters are defined in kernel/param.h. For example, to change the maximum number of processes from 64 to 128:
#define NPROC 128 // maximum number of processes2. Re-compile the kernel:
$ make clean
$ make qemu