m³OS docs GitHub

Phase 07

Core Servers

Use IPC to assemble the first useful userspace services and prove that the system can be structured as cooperating servers rather than one large kernel.

Complete

Learning goal

Understand service-oriented bootstrapping in a microkernel.

Category

infrastructure

Why this phase matters

Use IPC to assemble the first useful userspace services and prove that the system can be structured as cooperating servers rather than one large kernel.

How it works in m3OS

Phase 7 introduces the first layer of server infrastructure on top of the IPC engine built in Phase 6. The additions are:

Why structure output and input as servers?

A common question is: “why not just call the serial driver and keyboard driver directly?” The microkernel answer is policy/mechanism separation: Moving these decisions out of the kernel has concrete benefits:

How it builds on earlier phases

This phase builds on IPC Core and turns that foundation into Core Servers.

Implementation outline

  • Decide what the kernel launches directly and what init launches afterward.
  • Build the service registration model used for early discovery.
  • Move serial console behavior behind a console server.
  • Route keyboard notifications into a dedicated keyboard server.
  • Keep restart and crash handling simple but visible.

Task progress snapshot

19 of 19 tracked tasks are complete.

Documentation targets

  • Documentation deliverables have not been listed yet.

Deferred follow-on work

  • Automatic service restart policies
  • Complex capability delegation tooling
  • Dynamic driver loading
  • Servers running in ring 3 (requires ELF loader from Phase 8+)
  • String pointers via page grants for ring-3 IPC payloads
  • Service deregistration

Source materials

Important code

Code spotlight cards

Code spotlight

Implement init as the first userspace process

kernel/src/main.rs L93-L115

Implement init as the first userspace process. Why it matters: init (PID 1) anchors the entire userspace; every other service is spawned from it. Focus on `init_task` in `kernel/src/main.rs` while you trace the snippet.

/// init task: creates service endpoints, registers them, spawns servers.
fn init_task() -> ! {
    // Create IPC endpoint for the console service.
    let console_ep = ipc::endpoint::ENDPOINTS.lock().create();

    // Register in the service registry so clients can look it up by name.
    ipc::registry::register("console", console_ep)
        .expect("[init] failed to register console service");

    log::info!("[init] service registry: console={:?}", console_ep);

    // Spawn service tasks and a demo client.
    // kbd_server_task creates its own notification internally and does not
    // serve IPC clients in Phase 7 — no endpoint registration needed.
    task::spawn(console_server_task, "console");
    task::spawn(kbd_server_task, "kbd");
    task::spawn(console_client_task, "console-client");

    log::info!("[init] service set started — yielding");
    loop {
        task::yield_now();
    }
}

Code spotlight

Add a simple service registry for discovering early services

kernel/src/ipc/registry.rs L66-L69

Add a simple service registry for discovering early services. Why it matters: Clients need a well-known mechanism to find services by name without hardcoded endpoint IDs. Focus on `Registry` and `register` in `kernel/src/ipc/registry.rs` while you trace the snippet.

struct Registry {
    entries: [Option<Entry>; MAX_SERVICES],
    count: usize,
}

Code spotlight

Add a simple service registry for discovering early services

kernel-core/src/ipc/registry.rs L44-L49

Add a simple service registry for discovering early services. Why it matters: Clients need a well-known mechanism to find services by name without hardcoded endpoint IDs. Focus on `Registry` and `register` in `kernel-core/src/ipc/registry.rs` while you trace the snippet.

/// Dynamically growable service registry — name-to-endpoint mapping with
/// ownership tracking.
pub struct Registry {
    entries: Vec<Option<Entry>>,
    count: usize,
}

Key files

How real OSes differ

  • Production microkernels often have richer process managers, supervision trees, restart policies, and dynamic service discovery.
  • The toy design uses a very small service set and a transparent bootstrap flow so the architecture is easier to learn.

Success criteria

  • `init` starts the first service set successfully.
  • Clients can discover the console service and send output to it.
  • Keyboard events flow through `kbd_server` rather than directly into the kernel UI path.
  • Service startup ordering is documented and easy to follow.

Related phases

Keep exploring the roadmap