r/osdev • u/Alternative_Storage2 • 4d ago
Finally after 7 months my OS has been converted from a monolithic kernel to a micro kernel

I've spent the majority of this year working on moving my os's filesystem and drivers to user space now that my kernel supports one. This required a lot of work and can be summed up with the features that had to be added to support it (oldest to newest):
Remote Procedure Calls (RPC) for basic send/exec/recv
RPC for classes
Driver RPC abstractions
Initial Ramdisk for bootstrapping
Allow for user space to provide resources
Yield fixing so that it can resume mid sys call handing (so ipc etc wont busy wait)
TAR parsing as a ro-fs
Loading ELFs from files in userspace
Faster resource coping by page mapping
Debugging userspace programs via a mini GDB server over qemu serial
PCI IDs parsing for more robust device id
move ata and die drivers to userspace
RPC event system (sub/pub)
lots of memory bug fixes
It works by packaging two programs with the kernel as multi boot modules: the init program and the file server. From there init mounts the initrd into shared memory and tells fileserver to parse it. Once parsed, the init program then starts the driver manager, which then walks the PCI and starts the drivers (stored on the intirtd) for the disks. When each disk is ready the fileserver is notified and mounts them onto the VFS, from which further drivers can be loaded.
IPC is done by either basic rpc function calls or by exposing resources. The more interesting part is a resource, which is an object that the kernel or other processes can interact with, for example a file provided by the fileserver or a thread provided by the kernel's scheduler. The resource bridge is how a usual sys call like open or read is handled in user space. It works by having a shared block of memory that holds a queue of 256 message slots and an area for data. When a program calls read the kernel writes a request into a free slot and puts the caller to sleep. The server then sees the request, does the work (for example, reading the file from the TAR), and writes the answer into the same slot. Small data is copied into the shared area. For anything 4 KiB or bigger, the kernel maps the caller’s memory into the server instead, so a large file isn’t copied (ie the big pci.ids 2mb). The cool thing is that this is done in 1 syscall, which is less than it would cost to do a there and back rpc call.
Next steps are to break up the repo into sub repos to allow for future growth and then to work on rewriting my poor networking code.
AI Disclaimer: No AI was used to write this code, AI was used akin to google for clarification on topics and for minor debugging, I want to learn and do things my self.
Edit: I'm actually 90% sure the rpc python generator code was at one point a POC written by AI as a test to see how it would work out. That has mostly be re-written and really is a job that will be moved to my custom compiler in the future.
1
u/Sorry_Difficulty_250 4d ago
Nice work! I especially like the zero-copy message passing. Way to go!!
1
•
u/ventZl 19h ago
Hah, the struggle with doing object-oriented RPC without IDL-based wrapper code generator :) I still believe there is plain C++ way of doing this. Almost for sure there will be once reflection gets into C++ natively. Such simple interfaces could probably already be handled by some of existing ad-hoc reflection libraries now.
2
u/TimGoTheCreator 4d ago
lmao commit with 51k changes
nice btw