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.
Learning goal
Understand service-oriented bootstrapping in a microkernel.
Category
infrastructure
Components touched
Builds on
Unlocked by this phase
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
initlaunches 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
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
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
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
Phase 06
CompleteIPC Core
Turn the kernel into a real microkernel by making userspace services communicate through explicit message passing and capabilities.
Phase 08
CompleteStorage And VFS
Expose files through userspace services so programs can read named resources instead of relying on embedded data or ad hoc kernel hooks.