使用者空間的系統服務
如同任何基於微內核的作業系統,大多數的內核組件都已移至使用者空間,並經過調整以在其中運作。
一般而言,整體內核(Monolithic kernel)由於內核組件數量龐大,擁有數百個系統呼叫(system calls,即這些組件的介面),更不用說透過 ioctl 以及例如 procfs/sysfs 所提供的子系統呼叫數量。相較之下,微內核則僅有數十個系統呼叫。
這是因為非核心的內核組件被移至使用者空間,進而改為依賴 IPC,我們稍後會對此進行解釋。
User-space bootstrap is the first program launched by the kernel, and has a simple design. The kernel loads the initfs blob, containing both the bootstrap executable itself and the initfs image, that was passed from the boot loader. It creates an address space containing it, and jumps to a bootloader-provided offset. Bootstrap allocates a stack (in an Assembly stub), mprotects itself, and does the remaining steps to exec the init daemon. It also sets up the initfs scheme daemon.
The system calls used for IPC, are almost exclusively file-based. The kernel therefore has to know what schemes to forward certain system calls to. All file syscalls are marked with either SYS_CLASS_PATH or SYS_CLASS_FILE. The kernel associates paths with schemes by checking their scheme prefix against the scheme's name, in the former case, and in the latter case, the kernel simply remembers which scheme opened file descriptors originated from. Most IPC in general is done using schemes, with the exception of regular pipes like Linux has, which uses pipe2, read, write, close. Any scheme can also of course setup its own custom pipe-like IPC that also uses the aforementioned syscalls, like shm and chan from ipcd.
Schemes are implemented as a regular Rust trait in the kernel. Some builtin kernel schemes exist, which just implement that trait. Userspace schemes are provided via the UserScheme trait implementor, which relies on messages being sent between the kernel and the scheme daemon. This channel is created by scheme daemons when opening :SCHEME_NAME, which is parsed to the root scheme "" with path "SCHEME_NAME". Messages are sent by reading from and writing to that root scheme file descriptor.
So all file-based syscalls on files owned by user-space, will send a message to that scheme daemon, and when the result is sent back, the kernel will return that result back to the process doing the syscall.
Communication between user-space and the kernel, is generally fast, even though the current syscall handler implementation is somewhat unoptimized. Systems with Meltdown mitigations would be an exception, although such mitigations are not yet implemented.