← Back to all projects

LEARN SERENITYOS DEEP DIVE

Learn SerenityOS: From Contributor to Kernel Hacker

Goal: Deeply understand the SerenityOS operating system—from its core philosophy and architecture to building applications, hacking on the kernel, and making your first contribution to a truly from-scratch OS.


Why Learn SerenityOS?

SerenityOS is more than just an operating system; it’s a philosophy. It’s the belief that you can and should understand the entire software stack, from the bootloader to the web browser. By building everything in-house with a transparent, hackable approach, SerenityOS provides a unique learning opportunity that is lost in modern, heavily abstracted systems.

After completing these projects, you will:

  • Understand how a complete desktop operating system is architected.
  • Read and write modern, idiomatic C++ as practiced by the SerenityOS team.
  • Be able to build graphical applications, command-line utilities, and even kernel modules.
  • Navigate a large, complex, and active open-source C++ codebase.
  • Demystify the boundary between user-space and the kernel.
  • Have the skills and confidence to contribute to SerenityOS or any other large-scale systems project.

Core Concept Analysis

The SerenityOS Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                           Applications                                  │
│   (Browser, TextEditor, Terminal, File Manager, Games, etc.)            │
└─────────────────────────────────────────────────────────────────────────┘
                   │ ▲
                   │ │ (GUI, Core, IPC, etc.)
                   ▼ │
┌─────────────────────────────────────────────────────────────────────────┐
│                           System Libraries                              │
│                                                                         │
│ ┌──────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌────────┐ │
│ │  LibGUI  │ │ LibCore │ │ LibGfx  │ │ LibIPC  │ │ LibJS    │ │ LibC   │ │
│ └──────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ └────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
                   │ ▲
                   │ │ (System Calls)
                   ▼ │
┌─────────────────────────────────────────────────────────────────────────┐
│                            WindowServer                                 │
│      (Compositor, Event Handling, Window Management)                    │
└─────────────────────────────────────────────────────────────────────────┘
                   │ ▲
                   │ │ (System Calls)
                   ▼ │
┌─────────────────────────────────────────────────────────────────────────┐
│                                Kernel                                   │
│                                                                         │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐        │
│ │Scheduler │ │   VFS    │ │ Networking│ │ MemoryMgmt│ │ Drivers  │        │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘        │
└─────────────────────────────────────────────────────────────────────────┘

Project List

The following projects will guide you from a first-time builder to a potential core contributor.


Project 1: The First Boot

  • File: LEARN_SERENITYOS_DEEP_DIVE.md
  • Main Programming Language: Shell (for setup)
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: Build Systems / Toolchains
  • Software or Tool: CMake, QEMU, GCC/Clang
  • Main Book: The SerenityOS README.md and build documentation.

What you’ll build: A fully functional SerenityOS development environment where you can compile the entire OS from source and boot it in the QEMU emulator.

Why it teaches SerenityOS: This is the essential first step. You’ll learn the toolchain requirements, the structure of the source tree, and how the custom CMake-based build system works. Successfully booting the OS you compiled yourself is the “Hello, World!” of operating systems development.

Core challenges you’ll face:

  • Installing the correct dependencies → maps to understanding the toolchain
  • Running the build script → maps to learning the SerenityOS build process
  • Booting in QEMU → maps to virtualization and system emulation
  • Troubleshooting build failures → maps to learning to read compiler and linker errors

Resources for key challenges:

Key Concepts:

  • Toolchain Setup: SerenityOS Build Instructions
  • CMake Basics: Official CMake Tutorial
  • QEMU Emulation: QEMU User Documentation

Difficulty: Beginner Time estimate: A few hours Prerequisites: Familiarity with the command line, basic understanding of what a compiler is.

Real world outcome: You will have a QEMU window on your screen showing the full SerenityOS desktop, which you compiled from source code. You can click around, open the terminal, and explore the system you created.

Implementation Hints:

  1. Follow the official BuildInstructions.md for your host OS exactly.
  2. Pay close attention to the required versions of tools like CMake and GCC/Clang.
  3. The first build will take a long time as it builds the entire toolchain and OS. Be patient.
  4. Use the run script provided in the repository; it handles the QEMU invocation for you.
  5. If you encounter errors, the SerenityOS Discord community is very helpful for build issues.

Learning milestones:

  1. Toolchain builds successfully → You have a working cross-compiler.
  2. OS compiles without errors → You understand the basic build process.
  3. OS boots in QEMU → You have created a working operating system.

Project 2: “Hello, GUI!” Application

  • File: LEARN_SERENITYOS_DEEP_DIVE.md
  • Main Programming Language: C++
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: GUI Programming / Event Loops
  • Software or Tool: LibGUI, LibCore
  • Main Book: “Programming SerenityOS” (work-in-progress book by core developers)

What you’ll build: A simple graphical application that displays a window with a “Hello, World!” button. When you click the button, it prints a message to the debug console.

Why it teaches SerenityOS: This is your first step into user-space development. It introduces you to LibGUI (the widget toolkit), LibCore (the main event loop), and the basic structure of all SerenityOS applications. You’ll learn how to create windows, add widgets, and handle events.

Core challenges you’ll face:

  • Creating a Core::EventLoop → maps to understanding the heart of every application
  • Initializing a GUI::Window → maps to interacting with the WindowServer
  • Adding widgets to a window → maps to learning the GUI layout system
  • Handling button clicks with lambdas → maps to event-driven programming in SerenityOS

Resources for key challenges:

  • Explore existing applications in /Userland/Applications/ for examples (e.g., Calculator, TextEditor).
  • The LibGUI source code itself in /Userland/Libraries/LibGUI/.

Key Concepts:

  • Event Loop: “Programming SerenityOS” Ch. 3 (hypothetical, based on common structure)
  • Widget Hierarchy: Source code of any simple app like About.
  • IPC with WindowServer: Implicit in creating a GUI::Window.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Project 1, basic C++ knowledge (classes, lambdas).

Real world outcome: Your application will appear in the SerenityOS applications menu. When you run it, a window you designed will appear on the desktop. You can interact with it just like a native application.

Implementation Hints:

  1. Create a new directory in /Userland/Applications/ for your app.
  2. Create a CMakeLists.txt file, modeling it after a simple existing application.
  3. Your main function will need to:
    • Create a Core::EventLoop.
    • Create a GUI::Window.
    • Set the window’s main widget. You can use a GUI::Widget as a container.
    • Add a GUI::Button to the main widget.
    • Define the button’s on_click behavior.
    • Show the window and run the event loop (event_loop.exec()).
  4. Remember that SerenityOS uses modern C++ features extensively. Smart pointers (NonnullRefPtr, RefPtr) are common.

Learning milestones:

  1. Your app compiles and links → You understand the application build process.
  2. A window appears on the screen → You have successfully communicated with the WindowServer.
  3. The button responds to clicks → You understand the event handling mechanism.

Project 3: A cat Clone

  • File: LEARN_SERENITYOS_DEEP_DIVE.md
  • Main Programming Language: C++
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: File I/O / Command-Line Tools
  • Software or Tool: LibCore, LibMain
  • Main Book: “The C++ Programming Language” by Bjarne Stroustrup (for modern C++ idioms)

What you’ll build: A command-line utility, my_cat, that reads the contents of a specified file and prints them to standard output.

Why it teaches SerenityOS: This project moves away from the GUI and teaches you how fundamental system interactions work. You’ll learn about argument parsing, file I/O using Core::File, error handling, and the structure of a command-line program in SerenityOS.

Core challenges you’ll face:

  • Parsing command-line arguments → maps to using Core::ArgsParser
  • Opening and reading a file → maps to Core::File and its APIs
  • Handling I/O errors → maps to using the ErrorOr<T> pattern prevalent in SerenityOS
  • Writing to standard output → maps to basic console I/O

Key Concepts:

  • Error Handling: The ErrorOr<T> pattern is explained in SerenityOS’s Documentation/CodingStyle.md.
  • File I/O: Explore Userland/Libraries/LibCore/File.h.
  • Argument Parsing: Explore Userland/Libraries/LibCore/ArgsParser.h.

Difficulty: Intermediate Time estimate: A few hours Prerequisites: Project 1, basic C++.

Real world outcome: From the SerenityOS terminal, you can run $ my_cat /etc/motd and see the “message of the day” printed to the console, proving your tool can read files and interact with the shell.

Implementation Hints:

  1. Create a directory in /Userland/Utilities/.
  2. Your main will be wrapped by Core::System::main, which handles setup.
  3. Use Core::ArgsParser to define and parse the file path argument.
  4. Use Core::File::open to get a file object. This returns an ErrorOr<NonnullRefPtr<Core::File>>. You must handle the potential error.
  5. Read the file contents into a buffer. The read_entire_file method is convenient.
  6. Print the buffer’s contents to stdout.

Learning milestones:

  1. Arguments are parsed correctly → You can build robust command-line tools.
  2. File contents are printed → You understand file I/O.
  3. Errors are handled gracefully → You have mastered the SerenityOS error handling idiom.

Project 4: Add a Custom System Call

  • File: LEARN_SERENITYOS_DEEP_DIVE.md
  • Main Programming Language: C++
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Kernel Development / System Calls
  • Software or Tool: SerenityOS Kernel
  • Main Book: “Operating Systems: Three Easy Pieces” by Arpaci-Dusseau

What you’ll build: A new system call, uname_set_hostname, that allows a process (like a user-space utility) to change the system’s hostname. You will implement the syscall in the kernel and a utility to call it.

Why it teaches SerenityOS: This is a major leap. You will cross the user-space/kernel boundary for the first time. It demystifies how applications request services from the OS. You’ll learn the syscall definition process, where kernel code lives, and how to safely handle data from user-space.

Core challenges you’ll face:

  • Defining a new syscall → maps to modifying the Syscall.tbl file and kernel headers
  • Implementing the syscall handler → maps to writing C++ code inside the Kernel directory
  • Safely copying data from user-space → maps to understanding pointers and memory protection
  • Calling the syscall from a user-space program → maps to using the syscall() wrapper

Key Concepts:

  • Syscall Dispatch: Kernel/Syscall/handlers.cpp
  • User/Kernel Boundary: “Operating Systems: Three Easy Pieces” Ch. 6
  • Kernel Data Structures: Kernel/utsname.h for the hostname storage.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Projects 1 & 3, solid C++ understanding, conceptual knowledge of what an OS kernel is.

Real world outcome: You’ll have a new utility, sethostname, that you can run from the terminal. After running $ sethostname my-cool-os, the shell prompt will change to anon@my-cool-os, proving you have successfully modified kernel memory from a user-space command.

Implementation Hints:

  1. Define the syscall: Add uname_set_hostname to Kernel/Syscall/Syscall.tbl. This will auto-generate some code.
  2. Declare in LibC: Add the function prototype to Userland/Libraries/LibC/syscall.h and implement the wrapper in Userland/Libraries/LibC/syscall.c.
  3. Implement in Kernel: Add the handler function Kernel::Process::sys$uname_set_hostname in Kernel/Process.cpp.
  4. Kernel Logic: Your handler will need to copy the new hostname string from the user-space pointer into a kernel buffer. Look at other syscalls for examples of copy_from_user.
  5. User-space tool: Write a simple utility that takes a string and passes it to your new syscall wrapper.
  6. Rebuild the OS and run your new utility.

Learning milestones:

  1. The OS compiles with your new syscall → You understand the syscall definition process.
  2. Your utility calls the kernel code → You have successfully crossed the user/kernel boundary.
  3. The hostname changes → You have safely manipulated kernel state from user-space.

Project 5: A Custom GUI Widget

  • File: LEARN_SERENITYOS_DEEP_DIVE.md
  • Main Programming Language: C++
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: GUI Internals / Graphics Programming
  • Software or Tool: LibGUI, LibGfx
  • Main Book: The source code for LibGfx and LibGUI.

What you’ll build: A new GUI widget, ColorWheel, that displays a circular spectrum of colors. You’ll be able to add this widget to any GUI application.

Why it teaches SerenityOS: This project dives into the heart of the GUI toolkit. You’ll move beyond using widgets to creating them. This requires understanding the paint system (LibGfx), widget lifecycle events (paint_event, mousedown_event), and how to expose properties of your new widget.

Core challenges you’ll face:

  • Subclassing GUI::Widget → maps to the foundation of all widgets
  • Implementing the paint_event → maps to custom drawing with GUI::Painter and LibGfx
  • Handling mouse events → maps to making your widget interactive
  • Defining custom properties and events → maps to making your widget reusable

Key Concepts:

  • The Paint System: LibGfx/Painter.h and its drawing primitives.
  • Widget Events: LibGUI/Widget.h and the various *_event virtual methods.
  • Color Theory: Basic HSV/HSL to RGB conversion math for drawing the wheel.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 2, strong C++ (inheritance, virtual functions), basic computer graphics concepts.

Real world outcome: You’ll modify an application like Colors or build a new one to include your ColorWheel widget. You’ll be able to see your custom-drawn, interactive widget running as a native component of the SerenityOS desktop.

Implementation Hints:

  1. Create ColorWheel.h and ColorWheel.cpp inside Userland/Libraries/LibGUI/.
  2. Your ColorWheel class will inherit from GUI::Widget.
  3. The most important method to override is paint_event(GUI::PaintEvent& event). Inside, you’ll get a GUI::Painter object.
  4. In the paint event, you’ll loop through pixels or angles, calculate the corresponding color, and use painter.set_pixel() or other drawing commands.
  5. Override mousedown_event and mousemove_event to detect when the user clicks and drags on the wheel.
  6. You can add an on_color_change event (similar to on_click for buttons) that your widget can trigger, allowing apps to respond to color selection.

Learning milestones:

  1. Your custom widget appears, correctly drawn → You have mastered the LibGfx paint system.
  2. The widget responds to mouse clicks → You understand the GUI event system.
  3. Other applications can use your widget → You have successfully extended the native toolkit.

Project 6: A Basic Text Editor

  • File: LEARN_SERENITYOS_DEEP_DIVE.md
  • Main Programming Language: C++
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Application Development / Data Structures
  • Software or Tool: LibGUI, LibGfx, LibCore
  • Main Book: “Data Structures and Algorithms in C++” by Michael T. Goodrich

What you’ll build: A simple text editor from scratch. It will have a multi-line text area, a menu bar with “Open” and “Save” actions, and basic text editing capabilities.

Why it teaches SerenityOS: This is a rite of passage. Building a text editor forces you to integrate everything you’ve learned: file I/O (LibCore), GUI components (LibGUI), menu bars (GUI::Action), and text rendering (GUI::TextEditor). You’ll also need to think about data structures for storing the document’s contents efficiently.

Core challenges you’ll face:

  • Using the GUI::TextEditor widget → maps to the core of your application
  • Implementing “Open” and “Save” functionality → maps to file dialogs and Core::File
  • Creating a menu bar → maps to using GUI::Action and GUI::Menu
  • Managing the document state (modified, path, etc.) → maps to application-level logic

Key Concepts:

  • Actions and Menus: Look at how other apps create their File menu.
  • File Dialogs: GUI::MessageBox and GUI::FileChooser.
  • Text Widget: The GUI::TextEditor widget provides a lot of functionality out of the box.

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Projects 2 & 3, good C++ skills.

Real world outcome: You will have your own text editor running in SerenityOS. You’ll be able to create a new file, type text into it, save it, close the editor, and then re-open the file to see your text preserved.

Implementation Hints:

  1. Structure your application like in Project 2.
  2. Your main widget will be a GUI::TextEditor.
  3. Create a GUI::Menu for “File” and add GUI::Actions for “Open”, “Save”, and “Quit”.
  4. The “Open” action’s handler will create a GUI::FileChooser, get a file path, and use Core::File to read the contents into the GUI::TextEditor.
  5. The “Save” action’s handler will do the reverse.
  6. You can set the window title to reflect the current file path and whether it has unsaved changes.

Learning milestones:

  1. Text can be typed and displayed → You can use the core text widget.
  2. Files can be opened and their content loaded → You’ve integrated file I/O with your GUI.
  3. Files can be saved → You’ve completed the full application loop.
  4. The application feels like a native SerenityOS app → You’ve mastered the UI/UX conventions.

Project 7: Write a Game

  • File: LEARN_SERENITYOS_DEEP_DIVE.md
  • Main Programming Language: C++
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Game Loop / Graphics / Input Handling
  • Software or Tool: LibGUI, LibGfx, LibCore
  • Main Book: “Game Programming Patterns” by Robert Nystrom

What you’ll build: A clone of a classic arcade game like Pong or Snake.

Why it teaches SerenityOS: Games are a fun way to learn about real-time input, graphics, and application state management. Unlike a typical document-based app, a game requires you to constantly redraw the screen and update game logic, teaching you about timers and the main event loop in a different context.

Core challenges you’ll face:

  • Creating a game loop → maps to using Core::Timer to drive updates
  • Custom drawing → maps to using GUI::Painter to draw game elements instead of widgets
  • Handling real-time input → maps to overriding keydown_event on your main widget
  • Managing game state → maps to structuring your code to track score, positions, etc.

Key Concepts:

  • Timers: Core::Timer for periodic events.
  • Keyboard Events: GUI::KeyEvent for user input.
  • Custom Painting: Overriding paint_event on a GUI::Frame.

Difficulty: Intermediate Time estimate: 1-2 weeks

  • Prerequisites: Project 2, basic C++.

Real world outcome: You will have a playable game in the SerenityOS application menu. You can launch it and play, controlling the paddle or snake with your keyboard, all running natively inside the OS you built.

Implementation Hints:

  1. Your main application window will contain a custom widget that inherits from GUI::Frame. This will be your “canvas”.
  2. In your custom widget’s constructor, set up a Core::Timer that fires many times per second (e.g., 60). The timer’s on_timeout lambda will contain your main game logic (move ball, check for collisions) and then call update() to trigger a repaint.
  3. Override the paint_event on your widget. Use the GUI::Painter to draw the paddle, ball, score, etc.
  4. Override the keydown_event to handle keyboard input for moving the player’s paddle.
  5. Store your game state (ball position, paddle positions, score) as member variables in your widget class.

Learning milestones:

  1. A static scene is drawn → You can use the painter for custom graphics.
  2. The scene animates over time → You have a working game loop driven by a timer.
  3. The game responds to keyboard input → You have mastered real-time event handling.
  4. A complete game with win/loss conditions is playable → You have tied all the concepts together.

Summary

Project Main Programming Language
Project 1: The First Boot Shell (for setup)
Project 2: “Hello, GUI!” Application C++
Project 3: A cat Clone C++
Project 4: Add a Custom System Call C++
Project 5: A Custom GUI Widget C++
Project 6: A Basic Text Editor C++
Project 7: Write a Game C++