Phase 46
System Services
The OS has a service manager, system logging, and scheduled task execution. Services (sshd, telnetd, etc.) are managed by a unified init/service system that handles startup ordering, restart on failure, and clean shutdown. The OS behaves like a real server that can be administered remotely.
Learning goal
Understand how init systems (SysV init, systemd, runit) manage service lifecycles.
Category
infrastructure
Components touched
Builds on
Unlocked by this phase
Why this phase matters
The OS has a service manager, system logging, and scheduled task execution. Services (sshd, telnetd, etc.) are managed by a unified init/service system that handles startup ordering, restart on failure, and clean shutdown. The OS behaves like a real server that can be administered remotely.
How it works in m3OS
Phase 46 transforms m3OS from a system that hardcodes which daemons to run into one that reads service definitions from configuration files, starts them in dependency order, restarts them on failure, logs their output centrally, schedules recurring tasks, and shuts down cleanly. This is the layer that gives the later headless/reference release story a real operator-facing control plane.
How it builds on earlier phases
This phase builds on Ports System and turns that foundation into System Services.
Implementation outline
- Design the service definition file format (including
max_restart) and create/etc/services.d/entries. - Enhance init to parse service definitions and fill bidirectional dependency edges.
- Implement dependency-ordered startup (topological sort or iterative readiness check).
- Implement PID table mapping child PIDs to service entries for O(1) SIGCHLD dispatch.
- Implement
ServiceStatusstate machine enum (NeverStarted -> Starting -> Running -> Stopping -> Stopped). - Implement SIGCHLD-based service exit detection with PID table lookup and automatic restart (capped by
max_restart). - Write the
servicecommand (start, stop, restart, status, list). - Write
syslogd: bind/dev/log, accept connections, write to log files. - Write the
loggercommand. - Write
crond: parse crontab format, compute next run time, sleep-and-execute loop. - Write the
crontabcommand. - Implement
sys_reboot()syscall and kernel shutdown path. - Write
shutdownandrebootcommands. - Write/update
hostname,who,w,lastutilities. - Implement iterative reverse-dependency shutdown (find service with no unstopped dependents, stop it, repeat).
- Test full lifecycle: boot → services start → cron runs → remote login → shutdown.
Task progress snapshot
0 of 160 tracked tasks are complete.
Documentation targets
- Documentation deliverables have not been listed yet.
Deferred follow-on work
- Socket activation (systemd-style, as in rustysd)
- sd_notify readiness protocol (rustysd supports this; we use timeout-based heuristics)
- Service sandboxing (cgroups, namespaces)
- Journal (structured logging)
- Log rotation
- Remote syslog
- NTP time synchronization
- systemd-compatible unit files
- Runlevels / targets
Source materials
Important code
Code spotlight cards
Code spotlight
Create service definition files for existing daemons
spawn_sshd() calls in init. Creating them alongside the format design. Why it matters: These files replace the hardcoded spawn_telnetd() and. Focus on `spawn_telnetd` and `spawn_sshd` in `kernel/initrd/etc/services.d/sshd.conf` while you trace the snippet.
restart=always
max_restart=10
depends=syslogd Code spotlight
Implement service definition parser in init
parse them into structured ServiceDef values. This replaces the hardcoded. Why it matters: Init must read all .conf files from /etc/services.d/ and. Focus on `parse_service_def` and `ServiceDef` in `userspace/init/src/main.rs` while you trace the snippet.
/// Parse a service definition from a buffer of `key=value` lines.
fn parse_service_def(buf: &[u8], len: usize) -> Option<ServiceDef> {
let mut svc = ServiceDef::empty();
let mut pos = 0;
while pos < len {
// Skip whitespace and blank lines.
while pos < len && (buf[pos] == b' ' || buf[pos] == b'\t' || buf[pos] == b'\r') {
pos += 1;
}
if pos >= len {
break;
}
// Skip comment lines.
if buf[pos] == b'#' {
while pos < len && buf[pos] != b'\n' {
pos += 1;
}
if pos < len {
pos += 1;
}
continue;
}
if buf[pos] == b'\n' { Code spotlight
Create the `service` command binary
for the service manager. It must communicate with init to request operations. Why it matters: The service command is the primary administration interface. Focus on `service` and `main` in `userspace/coreutils-rs/src/service.rs` while you trace the snippet.
fn main(args: &[&str]) -> i32 {
if args.len() < 2 {
write_str(
STDERR_FILENO,
"usage: service {list|status|start|stop|restart} [name]\n",
);
return 1;
}
match args[1] {
"list" => cmd_list(),
"status" => {
if args.len() < 3 {
write_str(STDERR_FILENO, "usage: service status <name>\n");
return 1;
}
cmd_status(args[2])
}
"start" => {
if args.len() < 3 {
write_str(STDERR_FILENO, "usage: service start <name>\n");
return 1;
}
send_command("start", args[2]) Key files
- userspace/init/src/main.rs — PID 1 service manager: parser, dep graph, lifecycle, restart, shutdown
- userspace/syslogd/src/main.rs — System logging daemon: /dev/log socket, log formatting, file output
- userspace/crond/src/main.rs — Cron daemon: crontab parser, scheduler, job executor
- userspace/coreutils-rs/src/service.rs — service command: list, status, start, stop, restart
- userspace/coreutils-rs/src/logger.rs — logger command: send messages to syslog via /dev/log
- userspace/coreutils-rs/src/dmesg.rs — dmesg command: print kernel ring buffer from /proc/kmsg
- userspace/coreutils-rs/src/shutdown.rs — shutdown command: halt the system
- userspace/coreutils-rs/src/reboot_cmd.rs — reboot command: restart the system
- userspace/coreutils-rs/src/hostname.rs — hostname command: get/set hostname
- userspace/coreutils-rs/src/who.rs — who command: show logged-in users
- userspace/coreutils-rs/src/last.rs — last command: show login history
- userspace/coreutils-rs/src/crontab.rs — crontab command: manage user crontabs
- kernel/src/arch/x86_64/syscall.rs — sys_reboot syscall + kernel_shutdown helper
- userspace/syscall-lib/src/lib.rs — reboot() wrapper, signal constants
- kernel/initrd/etc/services.d/*.conf — Service definition files
How real OSes differ
- systemd: unit files, socket activation, cgroups, journal, timer units — enormous scope
- rustysd (MIT, Rust): systemd-compatible unit files, socket activation, sd_notify readiness protocol, thread-per-event model. Our PID table dispatch, service state machine, and reverse-order shutdown patterns are inspired by rustysd's design.
- runit: simple supervision tree, process 1/2/3 stages
- OpenRC: dependency-based init with parallel startup
- launchd (macOS): combines init, cron, inetd, and more
- Mailto on job output
- Timezone-aware scheduling
- Randomized delay
- Access control (cron.allow, cron.deny)
- Remote syslog (UDP/TCP to log servers)
- Facility/priority-based routing to different files
- Log rotation and compression
- Structured logging (RFC 5424)
Success criteria
- Services defined in `/etc/services.d/` start automatically at boot in dependency order.
- `service status sshd` shows the service is running with its PID.
- Killing a `restart=always` service causes it to be automatically restarted.
- A service that crashes more than `max_restart` times is marked permanently stopped.
- `service stop telnetd` cleanly stops the telnet server.
- Log messages from services appear in `/var/log/messages`.
- `logger "test message"` writes to the system log.
- A cron job scheduled for every minute executes on time.
- `shutdown` cleanly stops all services and halts the system.
- `reboot` cleanly restarts the system.
- `who` shows currently logged-in users.
Related phases
Keep exploring the roadmap
Phase 45
CompletePorts System
A simple BSD-style ports system enables building and installing third-party software inside the OS from source recipes. A port is a directory containing a Makefile, patches, and a Portfile that automates extracting, compiling, and installing a piece of software. At least 5 ports build and install successfully, with dependency resolution.
Phase 47
CompleteDoom
m3OS can run DOOM as a real full-screen graphical application. The game loads its WAD data from disk, renders through the framebuffer path, accepts keyboard input for gameplay, and returns the system to a usable administration path when it exits.