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.mdand 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:
- SerenityOS Build Instructions - The official and canonical guide.
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:
- Follow the official
BuildInstructions.mdfor your host OS exactly. - Pay close attention to the required versions of tools like CMake and GCC/Clang.
- The first build will take a long time as it builds the entire toolchain and OS. Be patient.
- Use the
runscript provided in the repository; it handles the QEMU invocation for you. - If you encounter errors, the SerenityOS Discord community is very helpful for build issues.
Learning milestones:
- Toolchain builds successfully → You have a working cross-compiler.
- OS compiles without errors → You understand the basic build process.
- 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
LibGUIsource 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:
- Create a new directory in
/Userland/Applications/for your app. - Create a
CMakeLists.txtfile, modeling it after a simple existing application. - Your
mainfunction will need to:- Create a
Core::EventLoop. - Create a
GUI::Window. - Set the window’s main widget. You can use a
GUI::Widgetas a container. - Add a
GUI::Buttonto the main widget. - Define the button’s
on_clickbehavior. - Show the window and run the event loop (
event_loop.exec()).
- Create a
- Remember that SerenityOS uses modern C++ features extensively. Smart pointers (
NonnullRefPtr,RefPtr) are common.
Learning milestones:
- Your app compiles and links → You understand the application build process.
- A window appears on the screen → You have successfully communicated with the WindowServer.
- 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::Fileand 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’sDocumentation/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:
- Create a directory in
/Userland/Utilities/. - Your
mainwill be wrapped byCore::System::main, which handles setup. - Use
Core::ArgsParserto define and parse the file path argument. - Use
Core::File::opento get a file object. This returns anErrorOr<NonnullRefPtr<Core::File>>. You must handle the potential error. - Read the file contents into a buffer. The
read_entire_filemethod is convenient. - Print the buffer’s contents to
stdout.
Learning milestones:
- Arguments are parsed correctly → You can build robust command-line tools.
- File contents are printed → You understand file I/O.
- 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.tblfile and kernel headers - Implementing the syscall handler → maps to writing C++ code inside the
Kerneldirectory - 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.hfor 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:
- Define the syscall: Add
uname_set_hostnametoKernel/Syscall/Syscall.tbl. This will auto-generate some code. - Declare in LibC: Add the function prototype to
Userland/Libraries/LibC/syscall.hand implement the wrapper inUserland/Libraries/LibC/syscall.c. - Implement in Kernel: Add the handler function
Kernel::Process::sys$uname_set_hostnameinKernel/Process.cpp. - 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. - User-space tool: Write a simple utility that takes a string and passes it to your new syscall wrapper.
- Rebuild the OS and run your new utility.
Learning milestones:
- The OS compiles with your new syscall → You understand the syscall definition process.
- Your utility calls the kernel code → You have successfully crossed the user/kernel boundary.
- 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
LibGfxandLibGUI.
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 withGUI::PainterandLibGfx - 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.hand its drawing primitives. - Widget Events:
LibGUI/Widget.hand the various*_eventvirtual 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:
- Create
ColorWheel.handColorWheel.cppinsideUserland/Libraries/LibGUI/. - Your
ColorWheelclass will inherit fromGUI::Widget. - The most important method to override is
paint_event(GUI::PaintEvent& event). Inside, you’ll get aGUI::Painterobject. - In the paint event, you’ll loop through pixels or angles, calculate the corresponding color, and use
painter.set_pixel()or other drawing commands. - Override
mousedown_eventandmousemove_eventto detect when the user clicks and drags on the wheel. - You can add an
on_color_changeevent (similar toon_clickfor buttons) that your widget can trigger, allowing apps to respond to color selection.
Learning milestones:
- Your custom widget appears, correctly drawn → You have mastered the
LibGfxpaint system. - The widget responds to mouse clicks → You understand the GUI event system.
- 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::TextEditorwidget → 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::ActionandGUI::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
Filemenu. - File Dialogs:
GUI::MessageBoxandGUI::FileChooser. - Text Widget: The
GUI::TextEditorwidget 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:
- Structure your application like in Project 2.
- Your main widget will be a
GUI::TextEditor. - Create a
GUI::Menufor “File” and addGUI::Actions for “Open”, “Save”, and “Quit”. - The “Open” action’s handler will create a
GUI::FileChooser, get a file path, and useCore::Fileto read the contents into theGUI::TextEditor. - The “Save” action’s handler will do the reverse.
- You can set the window title to reflect the current file path and whether it has unsaved changes.
Learning milestones:
- Text can be typed and displayed → You can use the core text widget.
- Files can be opened and their content loaded → You’ve integrated file I/O with your GUI.
- Files can be saved → You’ve completed the full application loop.
- 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::Timerto drive updates - Custom drawing → maps to using
GUI::Painterto draw game elements instead of widgets - Handling real-time input → maps to overriding
keydown_eventon your main widget - Managing game state → maps to structuring your code to track score, positions, etc.
Key Concepts:
- Timers:
Core::Timerfor periodic events. - Keyboard Events:
GUI::KeyEventfor user input. - Custom Painting: Overriding
paint_eventon aGUI::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:
- Your main application window will contain a custom widget that inherits from
GUI::Frame. This will be your “canvas”. - In your custom widget’s constructor, set up a
Core::Timerthat fires many times per second (e.g., 60). The timer’son_timeoutlambda will contain your main game logic (move ball, check for collisions) and then callupdate()to trigger a repaint. - Override the
paint_eventon your widget. Use theGUI::Painterto draw the paddle, ball, score, etc. - Override the
keydown_eventto handle keyboard input for moving the player’s paddle. - Store your game state (ball position, paddle positions, score) as member variables in your widget class.
Learning milestones:
- A static scene is drawn → You can use the painter for custom graphics.
- The scene animates over time → You have a working game loop driven by a timer.
- The game responds to keyboard input → You have mastered real-time event handling.
- 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++ |