liveBook · Manning

Operating system kernel

As explained in Rust in Action: Systems programming concepts and techniques

A kernel is the privileged core of an operating system that manages hardware resources and provides fundamental services for software execution.

An operating system kernel is the part of an OS that interacts with hardware, manages memory, and coordinates work. Full systems commonly coordinate processes and threads; a first kernel can do much less and still demonstrate how a computer starts running code without an existing OS. section 11.1

A Rust kernel cannot rely on an installed operating system or its usual standard library. Before it can run, the compiler needs a target definition describing the intended machine, and Rust’s core library must be built for that target. A bootloader then places the compiled kernel where it can run. section 11.2.1 section 11.2.3

A small build follows this path:

  • Define an x86-64 target with no operating system, then configure Cargo to build core and compiler_builtins for it. section 11.2.3
  • Compile the kernel and bootloader into a bootable image. The bootimage configuration makes cargo run launch that image in QEMU. section 11.2.1 section 11.2.3
  • Check the screen: this first kernel’s visible result is a pale blue box near the top-left corner. section 11.2.1
Listing 11.2 Kernel definition for FledgeOS
{
  "llvm-target": "x86_64-unknown-none",
  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
  "arch": "x86_64",
  "target-endian": "little",
  "target-pointer-width": "64",
  "target-c-int-width": "32",
  "os": "none",
  "linker": "rust-lld",
  "linker-flavor": "ld.lld",
  "executables": true,
  "features": "-mmx,-sse,+soft-float",
  "disable-redzone": true,
  "panic-strategy": "abort"
}

The target definition specifies an x86-64, 64-bit machine with no OS. It gives the compiler a concrete platform for the kernel rather than relying on a preinstalled target. section 11.2.3

A kernel also needs a different starting point from an ordinary program. It has no OS to return an exit code to, and its main loop does not return. A bootloader starts it; the linker uses the kernel’s _start symbol as its entry point. In this tiny kernel, _start contains the work itself instead of calling main(). section 11.2.6

Listing 11.4 Creating an OS kernel that paints a block of color
 1 #![no_std]                              #1
 2 #![no_main]                             #1
 3 #![feature(core_intrinsics)]            #2
 4   
 5 use core::intrinsics;                   #2
 6 use core::panic::PanicInfo;             #3
 7  
 8 #[panic_handler]
 9 #[no_mangle]
10 pub fn panic(_info: &PanicInfo) -> ! {
11   intrinsics::abort();                  #4
12 }
13  
14 #[no_mangle]
15 pub extern "C" fn _start() -> ! {
16   let framebuffer = 0xb8000 as *mut u8;
17  
18   unsafe {
19     framebuffer
20       .offset(1)                        #5
21       .write_volatile(0x30);            #6
22   }
23  
24   loop {}
25 }

The working kernel declares no_std and no_main, defines _start and a panic handler, then uses an unsafe volatile write to change a byte at a predefined framebuffer address. An endless loop keeps _start from returning. section 11.2.3

Run the first boot

From the fledgeos-0 project, run cargo +nightly run. The configured runner starts QEMU with the boot image; the colored box is the immediate check that the target build, bootloader, and kernel worked together. section 11.2.1 section 11.2.3

This is a starting kernel, not a complete OS: process and thread coordination remain beyond its scope. Direct interrupt handling is another substantial step because it changes kernel behavior; mistakes there can make the whole system unresponsive. section 11.1 section 12.1.1

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Works through a bootable kernel, custom target, and entry point, but stops short of implementing process or thread coordination.
Examples
Uses an x86-64 Rust kernel whose framebuffer write produces a colored box when booted in QEMU.
What it assumes
Builds on familiarity with ordinary Rust programs and Cargo while showing how kernels replace main and the usual standard-library target.
What you can do after
Build it from scratch as a minimal Rust kernel, package it with a bootloader, and run it in QEMU.
How it connects
Connects the kernel to bootloaders, compiler targets, memory-mapped output, and interrupts.

Also explained in

Compare how 2 books explain operating system kernel →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.