update docs

This commit is contained in:
2026-09-22 13:23:34 +08:00
parent 99bc3d15c5
commit 8a4788fca8
126 changed files with 7198 additions and 2425 deletions
+145
View File
@@ -0,0 +1,145 @@
# Services, readiness, and shutdown
Development reference and historical context. For current operating instructions, use the [user manual](../README.md). Acceptance applies only to the source and artifacts identified in each record.
[Documentation index](README.md) · [Native init and ARM VM](init.md) · [Cartridges](cartridges.md)
**Implemented in M2:** native s6 PID 1, a compiled base service graph, console
login, eudev, the Dasung controller, and a controllable test service. The
[init walkthrough](init.md) explains how to boot the ARM VM and try the commands
below. M6 adds the base cartridge service; M8 adds optional desktop/network profiles as described in the [desktop guide](desktop.md).
## Startup and service state
```text
Linux → /sbin/init → s6-linux-init → s6-svscan (PID 1)
└── rc.init → s6-rc-init → s6-rc change boot
```
The generated execline launcher immediately executes native init. Stage 1 prepares
writable `/run`, starts the catch-all logger, and replaces itself with s6-svscan.
Bash stage-2 scripts run as ordinary children. They initialize the live database
and activate the `boot` bundle. No service compiler runs during boot.
| Location in FDS | Purpose |
| --- | --- |
| `/etc/s6-rc/source` | Packaged, readable service definitions |
| `/etc/s6-rc/compiled` | Dependency database compiled under ARM emulation during the build |
| `/run/s6-rc` | Live service state on tmpfs |
| `/run/service` | Supervision directories created at runtime |
| `/run/uncaught-logs` | Native init catch-all log, also copied to the console |
| `/run/log/dasungd` | Rotating monitor-controller log |
These are guest paths, not instructions to start services on the Arch host.
The Void build container never boots the FDS service graph.
## The base boot graph
| Service | Function | Dependencies |
| --- | --- | --- |
| `runtime-fs` | Mount proc, sysfs, devpts and volatile temporary/log paths | Kernel or stage 0 supplies `/dev`; native stage 1 supplies `/run` |
| `hostname` | Set the image's hostname | None |
| `console` | Create volatile login accounting files | `runtime-fs` |
| `getty` | Provide a console login | `console`, `hostname` |
| `eudevd` | Process kernel device events | `runtime-fs`; readiness checked through its control channel |
| `udev-trigger` | Request initial subsystem and device events | Ready `eudevd` |
| `machine-config` | Validate internal NVMe settings and publish a fixed boot snapshot, or image defaults | `runtime-fs`; no console dependency |
| `cartridged-runtime` | Prepare bounded cartridge log storage | `runtime-fs` |
| `cartridged-log`, `cartridged` | USB events, bay inventory, validated mounts and IPC | Runtime paths and `machine-config`; no getty or eudev readiness dependency |
| `dasungd-runtime` | Prepare private controller state and log paths | `runtime-fs` |
| `dasungd-log`, `dasungd` | Supervise the monitor controller and its logger | Runtime paths and s6's logging pipeline |
The bundle selects these services through their dependencies; it does not impose
one serial list. Console startup does not wait for device enumeration, monitor
reconnection, networking, or cartridge discovery. Dasung remains part of the base,
independent of a GUI or an inserted ENVIRONMENT cartridge. See [Dasung](dasung.md).
M6 includes the real static `cartridged` service and its logger. Network, DHCP,
NTP, sshd, D-Bus, Xorg, WindowMaker,
Bluetooth, and Wi-Fi are absent from the current boot bundle.
## Inspect and control services
Inside the shell opened by `make vm`:
```sh
s6-rc -l /run/s6-rc -a list
s6-svstat /run/service/getty
s6-svstat /run/service/eudevd
s6-svstat /run/service/dasungd
cat /run/log/dasungd/current
s6-rc -l /run/s6-rc -u change test-echo
s6-svstat -o up,ready,pid /run/service/test-echo
printf 'hello\n' | s6-ipcclient /run/fds-test/echo.sock s6-ioconnect -t 3000
s6-rc -l /run/s6-rc -d change test-echo
```
`test-echo` is a root-only Unix-socket echo server. Its database entry ships in
this development rootfs, but it is excluded from the normal boot bundle. Its
`test-runtime` dependency creates `/run/fds-test` with mode 0700. The ARM boot
test verifies replies, a supervised restart with a new PID, and stop/start state
transitions. It also verifies that getty and Dasung are running without hardware.
## Readiness and failures
A process existing does not always mean its service is usable. The echo server
notifies s6 after it starts listening. Eudev has no native s6 notification, so
`s6-notifyoncheck` checks its control channel within a bounded deadline. The
initial device trigger does not wait for every unrelated device to settle.
There is no global `udevadm settle` or sleep added to hide a boot race. A missing
monitor leaves Dasung supervised and disconnected; it does not hold up getty.
Service errors go to the runtime logs and console. Investigate the failed
service and its dependencies instead of extending an arbitrary startup delay.
## Shutdown
`poweroff`, `reboot`, `halt`, and `shutdown` are the native s6-linux-init wrappers.
M10's `fds poweroff` and `fds reboot` first freeze new operations, stop optional
sessions and managed jobs, then verify DATA and cartridge unmounts. A native
shutdown hook also enforces this preparation for administrative use of the
wrappers. Only successful preparation proceeds to the remaining s6 service stop
and final kernel action. The two internal
s6-rc helper services are marked essential and remain until native final cleanup;
its diagnostic warnings about not stopping them are expected.
The [shutdown guide](power.md) explains commands, failure recovery and the current
M10 acceptance status. No physical Pi shutdown measurement is claimed. See
[Performance](performance.md) for the hardware targets and measurement boundaries.
M8 ENVIRONMENT profiles select OS-defined service bundles after console readiness.
Profile metadata is declarative; a cartridge cannot inject a root shell
script into startup. See [Cartridges](cartridges.md) for that trust boundary.
## Cartridge service
M6 adds `cartridged` and its bounded volatile logger to the base boot bundle.
It depends on runtime filesystem setup and M12 machine settings loading,
independently of getty and eudev. See [Internal storage](internal-storage.md) for
the read-only loading policy and explicit fallback diagnostics. Its
readiness notification means the control socket exists, not that all cartridges
have finished enumeration. Getty has no cartridge dependency.
The service listens before scanning and reconciles kernel USB/block events with
current sysfs state. See [Cartridges](cartridges.md) for configuration, controls,
restart behavior and diagnostics. Dasung stays a separate mandatory base service.
## Optional desktop and network graph
The `desktop` bundle selects `xserver` and `desktop-session`. Xorg's display-fd
notification establishes server readiness; the static session helper subscribes
to X11 property events before launching WindowMaker, then observes its EWMH
supporting-window property. This avoids missing an event when the atom does not
yet exist. Session processes run as fds in a root-owned cgroup. Their descendants
are stopped before Xorg. Native service supervision handles unexpected exits.
The `network` bundle selects `dhcp`. Its process readiness does not wait for a
lease; DHCP remains asynchronous. Both bundles have bounded volatile loggers,
and neither belongs to `boot`. Their runtime directories are prepared by
separate oneshots. See [Desktop and Ethernet](desktop.md) for user commands.
M10 places the DHCP client and its privilege-separated children in a root-owned
cgroup. Network stop checks actual group exit as well as the supervised main
process, then brings the managed interfaces down and clears volatile resolver
state. It introduces no additional daemon or boot dependency.