85 lines
4.3 KiB
Markdown
85 lines
4.3 KiB
Markdown
# Vision: a real-time microkernel
|
|
|
|
danos is aiming to be a **real-time operating system built on a microkernel** —
|
|
where drivers and services run isolated in user space for maximum stability, and
|
|
scheduling gives real guarantees about timing. This page is the north star: the
|
|
*why* that shapes every design decision below it. Read it before adding anything
|
|
structural.
|
|
|
|
## Microkernel
|
|
|
|
The kernel stays **minimal** — only what genuinely must run in privileged mode:
|
|
|
|
- scheduling,
|
|
- inter-process communication (IPC),
|
|
- memory management (address spaces, page tables),
|
|
- low-level interrupt dispatch.
|
|
|
|
Everything else — device drivers, filesystems, the network stack — runs as an
|
|
**isolated user-space server**, each in its own address space with only the
|
|
privileges it needs.
|
|
|
|
The payoff is **stability through isolation**. A driver bug can't corrupt the
|
|
kernel or another driver; a crashing service is contained and can be restarted,
|
|
while the rest of the system keeps running. That's the opposite of a monolithic
|
|
kernel, where a single driver fault can take everything down.
|
|
|
|
The cost is that **IPC becomes the backbone**: whatever used to be a function call
|
|
across a monolithic kernel is now a message between address spaces. In a
|
|
microkernel, IPC performance essentially *is* system performance (the lesson of
|
|
L4). So IPC must be fast, and it's a first-class concern, not an afterthought.
|
|
Hardware interrupts, too, become IPC: the kernel turns an IRQ into a message to the
|
|
driver task that owns that device.
|
|
|
|
## Real-time
|
|
|
|
danos schedules **preemptively, with guarantees about quanta** — the system must
|
|
be able to promise that a task runs when it's supposed to, within bounded time.
|
|
That imposes concrete requirements:
|
|
|
|
- **Fixed-priority preemptive scheduling.** The highest-priority ready task always
|
|
runs; a higher-priority task that becomes ready preempts a lower one immediately.
|
|
Not round-robin (which is fair but not predictable).
|
|
- **A calibrated, deterministic clock.** Guarantees measured in "quanta" are
|
|
meaningless on an arbitrary tick rate — real time requires a timer calibrated to
|
|
a known frequency.
|
|
- **Bounded interrupt latency.** Interrupt-disabled sections must be short and
|
|
bounded, so a ready high-priority task is never delayed by an unbounded kernel
|
|
operation.
|
|
- **Deterministic kernel operations.** Scheduling decisions should be O(1) (e.g. a
|
|
priority bitmap), not "walk a list of unknown length."
|
|
- **Priority inheritance** (once there are locks/IPC), so a high-priority task
|
|
blocked on a resource held by a low-priority one can't be delayed indefinitely by
|
|
a middle-priority task — bounding priority inversion.
|
|
|
|
A consequence worth stating early: the current [kernel heap](heap.md) is a
|
|
first-fit free list, which has **unbounded allocation time** and can fragment — it
|
|
is *not* real-time safe. It's fine for one-time kernel setup, but real-time paths
|
|
must pre-allocate or use a bounded (fixed-size pool) allocator. Don't allocate on a
|
|
hot real-time path.
|
|
|
|
## What this means for the roadmap
|
|
|
|
The vision reorders the obvious hobby-kernel path. Notably, **drivers are not
|
|
built into the kernel** — so an in-kernel keyboard driver would be throwaway work.
|
|
Input devices arrive later, as the *first user-space drivers*, once the machinery
|
|
to isolate them exists. The trajectory:
|
|
|
|
1. **Calibrated timer / clock** — a known-frequency, deterministic tick. The
|
|
foundation real-time quanta rest on. *(next)*
|
|
2. **Real-time scheduler** — fixed-priority preemptive, kernel threads first:
|
|
context switch, task struct, priority run-queue, timer-driven preemption.
|
|
3. **User mode + address-space isolation** — higher-half kernel, ring 3, per-process
|
|
page tables. The substrate for isolated servers.
|
|
4. **IPC** — fast message passing between address spaces. The microkernel's heart.
|
|
5. **User-space drivers** — interrupts delivered as IPC, plus MMIO/port-access
|
|
grants. The keyboard becomes the first one, validating the whole model.
|
|
|
|
## Where we are
|
|
|
|
The foundation is in place: UEFI boot, framebuffer + [serial](testing.md),
|
|
[physical frames](frame-allocator.md), [paging](paging.md) with W^X, [exceptions
|
|
and interrupts](interrupts.md), a [timer](device-interrupts.md), and a
|
|
[heap](heap.md) — plus a [test harness](testing.md). The kernel boots and has its
|
|
core services; the next milestones make it *schedule*, then *isolate*.
|