docs: architecture describes what is built now

kernel (threads, demand paging, TLB shootdowns, dynamic linking, RAM direct map), syscalls, filesystem (/proc, /sys,
/dev), terminals (12, VT handshake, ptys), networking (r8169 through LDLS), LDLS (module sets; Linux code may ship),
devices (what stays in the kernel; hybrid.md's lasting content), boot (the loader's placement of the kernel),
graphics (fbdev, GMMOS, QR 1-40), audio (ALSA over OSS), debugging, usb. New: packages.md (the apk root) and
desktop.md (Xorg on the framebuffer).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
Nexoniarz 2026-10-26 07:57:25 +01:00
commit 2556a955b3
15 changed files with 921 additions and 341 deletions

View file

@ -199,11 +199,14 @@ provides — reads and writes never reach it, because `fileread`/`filewrite` see
It is read-only: `dirlink` and `ialloc` answer `EROFS` rather than pretending.
A node exists because the kernel has the device, or it does not exist.
### What is there
### What is there in `/dev`
`console`, `null`, `keyboard`, `zero`, `full`, `random`, `urandom`, `tty`,
`stdin`, `stdout`, `stderr`, `fb0`, `mouse`, `hda`, `hdb`, and `input/event0`
and `input/event1` in one subdirectory.
`console`, `null`, `zero`, `full`, `random`, `urandom`, `tty`, `tty0` and
`tty1`..`tty12`, `stdin`, `stdout`, `stderr`, `keyboard`, `mouse`, `fb0`, `dsp`,
`ptmx` and a `pts/` directory of pseudo-terminal slaves, `hda`, `hdb`,
`input/event0`.., and the SchOS-specific `pci` (a device's registers, DMA and
interrupts, for a driver in a process), `netdev` (a network interface for a
process), `dbg` and `dbgro` (the kernel debugger's views).
Every disk and partition the block layer registered is there too, under the
name it was given (`sata0`, `sata0p2`, `nvme0p1`, `usb0p1`): major 8, minor its
@ -218,11 +221,18 @@ nothing behind it fails with `ENXIO`, which is a better answer than a missing
path — and with no node at all, `echo x > /dev/hdb` silently creates an ordinary
file of that name and appears to work.
### What is there
### What is there in `/proc`
Per-process directories, plus the global files: `meminfo`, `uptime`, `cpuinfo`,
`version`, `stat`, `loadavg`, `mounts`, `filesystems`, `schfs`, `pci`,
`interrupts`, `devices`, `netif`, and `sysrq`.
`/proc/self`, and one directory per process holding `stat`, `status`, `cmdline`,
`statm`, `comm`, `schedstat`, `maps`, `exe` (a symlink), `fd/` (a symlink per open
descriptor) and `task/` (one directory per thread). `maps` lists the file
mappings, and a process killed by a fault is told which file and offset it died
in.
The global files: `meminfo`, `uptime`, `cpuinfo`, `version`, `stat`, `loadavg`,
`mounts`, `filesystems`, `partitions`, `schfs`, `pci`, `interrupts`, `devices`,
`netif`, `resolv.conf`, `slab`, `fsstat`, `kmsg`, `strace`, `bootmode`,
`bootdebug`, `quiet`, `verbose`, `schinit` and `sysrq`.
**/proc is read-only except `sysrq`**, which is the one deliberate write target,
and the code says so in one place. Marking every procfs inode read-only once
@ -249,6 +259,8 @@ mounted by init with `mount("sysfs", "/sys", "sysfs", 0, 0)`.
| `/sys/firmware/memmap/N/` | `start end type`, the firmware's map as the loader handed it over |
| `/sys/firmware/efi/` | present when UEFI booted the kernel; empty |
| `/sys/class/dmi/id/` | `sys_vendor product_name product_version board_name bios_version`, and the rest Linux has, except serials and the UUID |
| `/sys/class/power_supply/` | `BAT0` (`capacity`, `status`, `energy_*`/`charge_*`, `voltage_now`, `cycle_count`, ...) and `AC` (`online`), from ACPI — the battery and the adapter are read through the laptop's embedded controller |
| `/sys/bus/pci/devices/…/` | also `boot_vga`, `enable` and `graphics/fb0`, which libpciaccess (and so Xorg) reads |
**Linux's layout because everything that reads hardware reads it from there.**
toybox's `lspci` and `lsusb` walk `/sys/bus/*/devices` and parse each `uevent`
@ -265,7 +277,8 @@ tables, `config`) report their real length, since tools copy them by it.
What is missing, compared with Linux: `/sys/devices` and its symlinks (the
`bus/*/devices` entries are directories rather than links into it),
`/sys/class` beyond `dmi`, `/sys/block`, and anything writable. PCI `config` is
`/sys/class` beyond `dmi` and `power_supply`, `/sys/block`, a uevent socket (so
no udev), and anything writable. PCI `config` is
256 bytes, because config space is read through port `0xCF8`, which reaches
no further.
@ -376,8 +389,6 @@ through.
- **No page cache.** `mmap` of a file reads the whole thing in at map time, and
writable `MAP_SHARED` of a file is refused rather than faked. This is the
single largest gap in the layer.
- **No symlinks in procfs**, which is why `/proc/<pid>/exe` is a regular file
and `ps -o comm` prints `[init]`.
- **`rename()` does not move directories**, and will not replace one. `EISDIR`
either way.
- **No named pipes.** `mkfifo()` fails with `EPERM`, Linux's answer for a
@ -385,19 +396,13 @@ through.
device, because `mknod()` read a Linux program's `(mode, dev)` as the native
`(major, minor)`: `ls -l` showed `crw-rw-rw- 438, 0` where a `p` belongs. The
zsh port was configured with `zsh_cv_sys_fifo=yes` on the strength of that.
- **No `/dev/fd`, and no `/proc/self`.** A process cannot reach its own open
descriptors by path. `<(cmd)` needs one or the other — zsh now knows it has
neither and says so.
- **No `AF_UNIX` socket inodes.** Socket names live in a table in
`kernel/net/unix.c`, so `bind()` creates nothing that can be `stat()`ed or
`unlink()`ed.
- **No `/sys/devices` and no uevents**, so nothing can be told that a device
appeared; Xorg is given its input devices by a config file instead.
- **No unified inode cache across filesystems** beyond the single `itable`.
- **A known, un-root-caused hang:** heavy `ls -lR` use across many commands in
one long shell session can eventually make a *later*, unrelated directory
hang; the identical command succeeds on a fresh boot. It is not inode or file
table exhaustion — both fail cleanly and neither fired. It smells like a lock
or refcount leak in the `*at()` paths or in toybox's own fd handling. The next
step is instrumenting `itable`/`ftable` occupancy across a long session to see
what is climbing.
- **`sys_delete`/`sys_show`/`sys_showstat`** are orphaned entries from the old
v1 filesystem's recycle bin. Nothing reaches them and they die with `fs.c`.
- **One long-standing hang was never found.** Heavy `ls -lR` use across many
commands in one long shell session once made a *later*, unrelated directory
hang; the identical command succeeded on a fresh boot. It was instrumented and
hunted and could not be reproduced, which is recorded in
[../history/kernel.md](../history/kernel.md) rather than forgotten.