mirror of
https://github.com/troglobit/finit.git
synced 2026-10-15 10:29:35 +00:00
doc: rewrite keventd documentation for unified device manager
Rewrite doc/keventd.md from a 14-line stub into comprehensive documentation covering all features of the new unified keventd: device node creation, persistent symlinks, firmware loading, module loading, coldplug, conditions, and command-line usage. Update doc/conditions.md to list keventd as the primary provider of dev/* and sys/pwr/* conditions, with devmon as fallback when an external device manager is used instead. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
3 files changed
+221
-19
No files matched your search
+10
-6
@@ -177,15 +177,19 @@ Built-in Conditions
|
||||
|
||||
Finit comes with a set of plugins for conditions:
|
||||
|
||||
- `devmon` (built-in)
|
||||
- `netlink`
|
||||
- `pidfile`
|
||||
- `keventd`: provides `<dev/...>` and `<sys/pwr/...>`
|
||||
- `devmon` (built-in fallback for `<dev/...>` without keventd)
|
||||
- `netlink`: provides `<net/...>`
|
||||
- `pidfile`: provides `<pid/...>`
|
||||
- `sys`
|
||||
- `usr`
|
||||
|
||||
The `devmon` (built-in) plugin monitors `/dev` and `/dev/dir` for device
|
||||
nodes being created and removed. It is active only when a run, task, or
|
||||
service has declared a `<dev/foo>` or `<dev/dir/bar>` condition.
|
||||
The `dev/` conditions are provided by `keventd`, the built-in device
|
||||
manager. When keventd creates a device node in `/dev`, it also asserts
|
||||
the corresponding `dev/` condition. When a device is removed, the
|
||||
condition is cleared. If keventd is not in use (an external device
|
||||
manager like udevd is used instead), the `devmon` built-in provides the
|
||||
same conditions by monitoring `/dev` and `/dev/dir` with inotify.
|
||||
|
||||
The `pidfile` plugin recursively watches `/run/` for PID files created
|
||||
by the monitored services, and sets a corresponding condition in the
|
||||
|
||||
@@ -125,8 +125,10 @@ Load kernel modules, each with optional arguments. Similar to the
|
||||
Deprecated, there is both a `modules-load.so` and a `modprobe.so` plugin
|
||||
that can handle module loading better. The former supports loading from
|
||||
`/etc/modules-load.d/`, the latter uses kernel modinfo to automatically
|
||||
load (or coldplug) every required module. For hotplug we recommend the
|
||||
BusyBox mdev tool, add to `/etc/mdev.conf`:
|
||||
load (or coldplug) every required module. Hotplug module loading is
|
||||
handled by [keventd](../keventd.md), the built-in device manager. On
|
||||
systems using the hotplug plugin with BusyBox mdev instead, add to
|
||||
`/etc/mdev.conf`:
|
||||
|
||||
$MODALIAS=.* root:root 0660 @modprobe -b "$MODALIAS"
|
||||
|
||||
|
||||
+207
-11
@@ -1,14 +1,210 @@
|
||||
keventd
|
||||
=======
|
||||
Bundled Device Manager
|
||||
======================
|
||||
|
||||
The kernel event daemon bundled with Finit is a simple uevent monitor
|
||||
for `/sys/class/power_supply`. It provides the `sys/pwr/ac` condition,
|
||||
which can be useful to prevent power hungry services like anacron to run
|
||||
when a laptop is only running on battery, for instance.
|
||||
The kernel event daemon `keventd` is a built-in device manager bundled
|
||||
with Finit. It replaces the need for external device managers like
|
||||
mdev, mdevd, or udevd on systems where a lighter-weight solution is
|
||||
preferred, particularly on embedded systems.
|
||||
|
||||
Since keventd is not an integral part of Finit yet it is not enabled by
|
||||
default. Enable it using `./configure --with-keventd`. The bundled
|
||||
`contrib/` build scripts for Debian, Alpine, and Void have this enabled.
|
||||
It is enabled by default since Finit v5. To disable it and use an
|
||||
external device manager instead: `./configure --without-keventd`
|
||||
|
||||
This daemon is planned to be extended with monitoring of other uevents,
|
||||
patches and ideas are welcome in the issue tracker.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
When started, keventd listens on a `NETLINK_KOBJECT_UEVENT` socket for
|
||||
kernel events and handles:
|
||||
|
||||
- **Device node creation**: creates and removes `/dev` nodes with
|
||||
correct permissions on device add/remove events
|
||||
- **Persistent symlinks**: creates `/dev/disk/by-id/`, `/dev/disk/by-path/`,
|
||||
and `/dev/input/by-id/`, `/dev/input/by-path/` symlinks for stable
|
||||
device naming
|
||||
- **Firmware loading**: responds to kernel firmware requests by searching
|
||||
`/lib/firmware/` and writing firmware data to sysfs
|
||||
- **Module loading**: parses `MODALIAS` from uevents and spawns `modprobe`
|
||||
to load the appropriate kernel module
|
||||
- **Coldplug**: with the `-c` flag, walks `/sys/devices` and triggers
|
||||
add events for all devices present at boot
|
||||
- **Power supply monitoring**: tracks AC power status and provides the
|
||||
`sys/pwr/ac` condition
|
||||
- **Device conditions**: sets `dev/*` conditions in the Finit condition
|
||||
system when device nodes appear or disappear
|
||||
|
||||
|
||||
Device Nodes
|
||||
------------
|
||||
|
||||
On receiving an `add` event with `MAJOR`, `MINOR`, and `DEVNAME`
|
||||
fields, keventd creates the corresponding device node in `/dev` using
|
||||
`mknod()`. Parent directories are created automatically (e.g.,
|
||||
`/dev/input/` for `/dev/input/event0`).
|
||||
|
||||
On `remove` events, the device node and its associated symlinks and
|
||||
conditions are cleaned up.
|
||||
|
||||
### Default Permissions
|
||||
|
||||
keventd applies permissions based on built-in rules that match on
|
||||
device subsystem and name:
|
||||
|
||||
| Subsystem | Pattern | Mode | Owner:Group |
|
||||
|---------------|-------------|--------|----------------|
|
||||
| block | sd*, vd*, nvme*, mmcblk*, loop*, dm-*, md* | 0660 | root:disk |
|
||||
| tty | tty[0-9]* | 0620 | root:tty |
|
||||
| tty | ttyS*, ttyUSB*, ttyACM* | 0660 | root:dialout |
|
||||
| input | event*, mouse*, mice | 0660 | root:root |
|
||||
| sound | * | 0660 | root:audio |
|
||||
| video4linux | * | 0660 | root:video |
|
||||
| drm | card*, render* | 0660 | root:video |
|
||||
| (any) | null, zero, full, random, urandom | 0666 | root:root |
|
||||
| (any) | console | 0600 | root:root |
|
||||
| (default) | | 0660 | root:root |
|
||||
|
||||
|
||||
Persistent Symlinks
|
||||
-------------------
|
||||
|
||||
For block devices, keventd creates symlinks under `/dev/disk/`:
|
||||
|
||||
- **by-id**: based on the device serial number and model, read from
|
||||
sysfs attributes (`/sys/.../device/vendor`, `model`, `serial`)
|
||||
- **by-path**: based on the device topology path
|
||||
|
||||
For input devices, symlinks are created under `/dev/input/`:
|
||||
|
||||
- **by-id**: based on the device name from sysfs
|
||||
- **by-path**: based on the physical device path
|
||||
|
||||
These symlinks are tracked internally and automatically removed when the
|
||||
corresponding device is unplugged.
|
||||
|
||||
|
||||
Firmware Loading
|
||||
----------------
|
||||
|
||||
When a kernel driver requests firmware (via `request_firmware()`), the
|
||||
kernel sends a uevent with a `FIRMWARE=` field. keventd handles this
|
||||
by:
|
||||
|
||||
1. Searching for the firmware file in order:
|
||||
- `/lib/firmware/updates/<kernel-version>/<name>`
|
||||
- `/lib/firmware/updates/<name>`
|
||||
- `/lib/firmware/<kernel-version>/<name>`
|
||||
- `/lib/firmware/<name>`
|
||||
2. Writing `1` to `/sys/<devpath>/loading` to signal start
|
||||
3. Copying the firmware data to `/sys/<devpath>/data`
|
||||
4. Writing `0` to `/sys/<devpath>/loading` on success (or `-1` on failure)
|
||||
|
||||
This is particularly important early in boot when drivers for graphics
|
||||
cards, network adapters, and other hardware need firmware before they
|
||||
can operate.
|
||||
|
||||
|
||||
Module Loading
|
||||
--------------
|
||||
|
||||
When a device add event includes a `MODALIAS` field, keventd spawns
|
||||
`modprobe -bq <modalias>` to load the matching kernel module. Module
|
||||
loading is done asynchronously (keventd does not wait for modprobe to
|
||||
complete) to avoid blocking other event processing.
|
||||
|
||||
|
||||
Coldplug
|
||||
--------
|
||||
|
||||
To handle devices that were present before keventd started, it supports
|
||||
a coldplug mode activated with the `-c` flag. This walks the entire
|
||||
`/sys/devices` tree and writes `add` to each `uevent` file, causing the
|
||||
kernel to re-emit add events for all existing devices.
|
||||
|
||||
This replaces the separate `coldplug` script previously used with mdev.
|
||||
|
||||
|
||||
Conditions
|
||||
----------
|
||||
|
||||
keventd provides conditions in two namespaces:
|
||||
|
||||
### Device Conditions (`dev/`)
|
||||
|
||||
When a device node is created, keventd asserts a corresponding condition
|
||||
in `/run/finit/cond/dev/`. This allows services to wait for specific
|
||||
devices:
|
||||
|
||||
service mdadm {
|
||||
description = "RAID monitor"
|
||||
runlevel = "2345"
|
||||
conditions = { "dev/sda" }
|
||||
command = "/usr/sbin/mdadm --monitor /dev/md0"
|
||||
}
|
||||
|
||||
service gps-daemon {
|
||||
description = "GPS daemon"
|
||||
runlevel = "2345"
|
||||
conditions = { "dev/ttyUSB0" }
|
||||
command = "/usr/sbin/gps-daemon"
|
||||
}
|
||||
|
||||
When the device is removed, the condition is cleared and Finit stops
|
||||
the dependent services.
|
||||
|
||||
### Power Supply Conditions (`sys/pwr/`)
|
||||
|
||||
keventd monitors the `power_supply` subsystem and provides:
|
||||
|
||||
- `sys/pwr/ac` -- asserted when AC power is connected
|
||||
|
||||
This is useful for preventing power-hungry services from running on
|
||||
battery:
|
||||
|
||||
service cron {
|
||||
description = "Cron daemon"
|
||||
runlevel = "2345"
|
||||
conditions = { "sys/pwr/ac", "pid/syslogd" }
|
||||
command = "cron -f"
|
||||
}
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
keventd [-cdhnv]
|
||||
|
||||
Options:
|
||||
-c Run coldplug at startup
|
||||
-d Enable debug mode (foreground, verbose)
|
||||
-h Show help text
|
||||
-n Run in foreground (no daemon)
|
||||
-v Show version
|
||||
|
||||
In normal operation, Finit starts keventd automatically via its system
|
||||
configuration. The `-d` flag is useful for debugging device issues --
|
||||
it runs keventd in the foreground and logs all received uevents.
|
||||
|
||||
Debug logging can also be toggled at runtime by sending `SIGUSR1`:
|
||||
|
||||
kill -USR1 $(pidof keventd)
|
||||
|
||||
|
||||
Integration with Finit
|
||||
----------------------
|
||||
|
||||
keventd is a standalone daemon started by Finit as an internal service.
|
||||
It communicates with Finit exclusively through the filesystem-based
|
||||
condition system -- creating and removing symlinks in `/run/finit/cond/`.
|
||||
|
||||
This means keventd can also be tested independently:
|
||||
|
||||
# Run in debug mode to see all kernel events
|
||||
keventd -d
|
||||
|
||||
# Run with coldplug to populate /dev from scratch
|
||||
keventd -c -n
|
||||
|
||||
When keventd is enabled, it conflicts with external device managers.
|
||||
Only one device manager should be active at a time. The system
|
||||
configuration uses the `conflict:` directive to enforce this:
|
||||
|
||||
service conflict:udevd,mdevd,mdev [...] keventd -c -- Finit device manager
|
||||
Reference in new issue
Block a user