SchOS/docs/architecture/udev.md
Nexoniarz b3f72cd95e eudev starts at boot; Xorg finds its input devices through it
udevd and a one-shot trigger run from schinit, 10-schos.conf no longer lists
event0/event1, and the docs say what udev covers and what it does not.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
2026-10-26 11:44:21 +01:00

4.2 KiB

udev

Alpine's eudev runs on SchOS as an ordinary process, started by schinit (etc/schinit/udevd.job, with udev-trigger.job replaying the devices that were there first). It is what lets Xorg find its keyboard and mouse instead of being told, and the road to a Wayland compositor starts here: libinput and libseat both ask udev what exists.

The kernel's half is three pieces, all small, none of them specific to udev.

The device table: kernel/dev/kdev.c

The devices the kernel implements itself — input event nodes, the memory devices, terminals, the framebuffer, the disks — are listed once, with their class, name, /dev name and parent. Everything below is generated from it.

The device numbers are the ones stat() reports for the node, not SchOS's internal ones: /dev/tty1 is 4:1 to a Linux program (linux_tty_rdev in kernel/sys/sys_fs.c), and udev compares what it reads in /sys with what stat() says about the node. dev_stat_numbers() is the one mapping both use.

/sys: kernel/fs/sysfs.c

/sys/devices/virtual/input/input0/            name capabilities/{ev,key,rel,abs} properties
/sys/devices/virtual/input/input0/event0/     dev  uevent  subsystem -> ../../../../../class/input
/sys/class/input/event0                       -> ../../devices/virtual/input/input0/event0
/sys/dev/char/13:64 ...                       -> ../../devices/virtual/...

Symlinks are real (T_SYMLINK inodes whose target is generated). uevent is readable (DEVPATH=, SUBSYSTEM=, MAJOR=, MINOR=, DEVNAME=) and writable: echo add > uevent — which is what udevadm trigger does — makes the kernel announce the device again. A write to a PCI or USB device's uevent is accepted and says nothing yet, because those devices are not in the /sys/devices tree and an event's DEVPATH has to name something that exists.

The input capability files are what input_id reads to decide ID_INPUT_KEYBOARD or ID_INPUT_MOUSE. SchOS has two input devices whatever the machine — every keyboard on event0, every mouse on event1 (kernel/dev/input.c) — so each has a fixed, plausible capability set.

/dev: kernel/fs/devfs.c

devtmpfs is no longer read-only: udev creates /dev/char/MAJ:MIN, /dev/fd, /dev/input/by-* and the like. A small in-memory overlay (192 entries) holds directories and symlinks, listed after the kernel's own nodes in whichever directory they are in. Device nodes themselves are still the kernel's: mknod and regular files in /dev are refused.

The sockets: kernel/net/unix.c

  • AF_UNIX SOCK_DGRAM and SOCK_SEQPACKET keep message boundaries. udevd's control socket is SEQPACKET, and its manager and workers talk over a DGRAM socketpair. A message carries its sender's credentials with it (several workers share one end), a zero-length datagram is a datagram, and a datagram socket never reads end-of-stream.
  • AF_NETLINK / NETLINK_KOBJECT_UEVENT sockets bind to multicast groups: group 1 is the kernel's events, group 2 is what udevd re-announces once its rules have run. A datagram can also be addressed to a port id — udevd hands an event to an idle worker that way, and the worker believes it only from the manager's port. The kernel's messages arrive as credentials with uid 0, pid 0. A queue that is full drops the message, as Linux does, and udevadm trigger is how a reader recovers.

What is not there

  • PCI and USB devices in /sys/devices, and add/remove events from the hotplug thread. A USB keyboard works because every keyboard is event0, not because udev knew it arrived.
  • hwdb (/etc/udev/hwdb.bin): udevadm hwdb --update has not been run in the image, so 60-input-id logs "returned non-zero" for the hwdb import. The properties that matter come from input_id.
  • Block device partitions, by-id / by-uuid links, and a /sys/block.
  • libinput and libseat (next; see ../plan/roadmap.md).

Testing

Boot the ISO and run udevd --debug &, then udevadm trigger; udevadm settle. /run/udev/data/c7:0 should contain ID_INPUT_KEYBOARD=1, and udevadm info /dev/input/event0 should print the device. Under X, /var/log/Xorg.0.log says config/udev: Adding input device.