4 ms·
This is super cool! I’ve had an idea I’ve been wanting to build into an OS for ages - where we use versions, message passing and structured patches to pass inf
by josephg 3y ago
This is super cool!
I’ve had an idea I’ve been wanting to build into an OS for ages - where we use versions, message passing and structured patches to pass information between the kernel and application processes. So an application can subscribe to a file / USB device state / list of running processes / anything using a common, standard API. But it sounds really daunting to try and hack something like into the Linux kernel or something in one go.
If I want to experiment with something like this, what do you recommend? How hard would it be to do something like that in a hobby kernel like Axle?
- blown_gasket 3y agoI've been pondering this for a moment and if I were to write an application for such a system I don't think I'd enjoy it. If you want to pass information from the kernel and bubble that all the way to the application to do something with it, I would think you now have to write signal handling in your application.
- josephg 3y agoObviously, the signal handling code can live in a library of some sort. With a generic, system wide api there’s no reason you couldn’t still poll if you really wanted to. But maybe at least with a version token. So the application can say “I want info on which processes are running. Last time I asked, you gave me token 5827275” and the kernel can respond and say “you’ve got the most recent version of that data already champ”.
- ww520 3y agoLinux exposes system information like processes and devices in the psuedo file system hosted at the mount point /proc. Any user mode programs can use the standard file IO API to access them. Some of the "files" like /proc/self/mounts are pollable, i.e. a program can use blocking select to wait for changes like when a new file system has been mounted.
- josephg 3y agoYeah, I know how it works in linux. I just hate it. Polling and writing a parser for a pseudo-file always seems like a super roundabout, inefficient, brittle way to send information from kernel to userspace. Think about it - the kernel stores some data in a nice, neat struct. And the kernel knows exactly when that struct is modified. Userspace wants that data, and wants to know when the data changes. So every second, userspace "reads" a pseudo file. The kernel packs the struct's contents into a big string with some sloppy, hand written text format and passes it to userspace. Then in userspace you need to write a brittle parser for whatever the kernel gives you, knowing that in different versions of the kernel you'll get slightly differently formatted strings. When the data changes in the kernel, the application has no way of being notified. It just polls and parses in a loop. Its both inefficient (when there are no changes, its all wasted effort). And its laggy (when changes happen, it'll take your application up to the polling interval to find out about the changes). For things like filesystem watching, there are special APIs applications can consume. But those APIs are different for every kind of data the kernel manages. Devices, mount points, USB connectivity, filesystem watching, CPU usage, thermal sensors, open network connections and on and on. All of this stuff has totally different kernel-level APIs for "watching" changes. (If you're lucky - a lot of it can only be polled). Its a big fat mess. I want to try replacing all of that with a nice clean API for fetching & subscribing to any kind of data. So, the kernel has a standard API for fetching (maybe it returns JSON). And a standard API for subscribing to changes - such that your application is notified when a change occurs, and the change is sent in a standard, easily digestible patch format. And ideally, eventually, I'd like applications to be able to share their own changes back with the kernel in the same form & format. And maybe, share data objects between applications like that - with the kernel acting as a broker for sending patches back and forth, and syncing them with the filesystem. I think that would be really neat and useful for all sorts of applications. But I want to prototype it all first in something thats not linux. I'm just not sure where to start. I don't really want to write an OS from scratch just to try out this generic state passing idea.
- deleted 3y ago[deleted]
- 3y ago
- rajeevk 3y agoThere are a lot of resources here in case you want to write a kernel from scratch. https://wiki.osdev.org/Main_Page https://wiki.osdev.org/Main_Page I wrote a unix-like kernel from scratch long back. It was not a fully functional unix but had a lot of components ready to the extent it would provide a command line interfaceI from which you can run commands like ls, cat etc by loading elf executables. I would highly recommend to read this tutorial http://www.osdever.net/bkerndev/Docs/title.htm http://www.osdever.net/bkerndev/Docs/title.htm Feel free to reach out to me (email in my profile page) if you want to discuss the topic with me.
- codyd51 3y agoHi, author here! Thanks for the kind words! I'll echo rajeevk's recommendation: the OSDev wiki is full of useful documentation and guides for setting up a bare-metal toolchain. There's also a community forum with a wealth of knowledge just waiting to be read. In terms of boots on the ground, I remember once seeing a mantra from someone on the OSDev forums that went something like this: building an x86 OS is first about getting the CPU into a usable state, then about getting as far away from it as possible. This is really true! There's a lot of work to do to set up the features that any modern environment needs as a baseline: paging, segmentation, interrupt descriptors, etc, but once you're done with all that you're free to roam in the design space and build whatever you like, however you imagine, building abstractions and then abstractions on top of those. I'd liken the early stages of OS development to a tech tree in a video game: you need serial output so that you can debug your kernel. You need to be able to allocate memory so that you can create pixel buffers, then need drawing primitives to fill them up. You need processes, and a scheduler to coordinate them. Every new feature you add opens up a myriad of possibilities that weren't there before, and although many things have a serial list of dependencies, there's always so much to do that you can just focus on whatever feels particularly inspiring to you at any given time. It's really a lot of fun. axle also uses structured messages for making requests to the kernel, as well as everything else. Here's an example of some structured requests that can be sent to the kernel: https://github.com/codyd51/axle/blob/paging-demo/kernel/kernel/util/amc/core_commands.h https://github.com/codyd51/axle/blob/paging-demo/kernel/kern.... Here's some structured data that an application (in this case, the window manager) uses to interact with other apps: https://github.com/codyd51/axle/blob/paging-demo/rust_programs/awm_messages/src/lib.rs https://github.com/codyd51/axle/blob/paging-demo/rust_progra... All the best, and feel free to reach out to me as well!
- josephg 3y agoThanks for the links and encouragement! I suppose my main hesitation is that it seems like an awful lot of work to build all that from scratch. I really want to - it looks super fun. But I've got my hands totally full at the moment building a CRDT & data engine for local first software. I really just have one idea I want to explore, which is this idea around sharing state between the kernel and userland via subscriptions and patches. (By taking some ideas from event sourcing and things like that). I guess I'm trying to figure out where I would even start prototyping something like that. I guess I could just fork axle and hack on it a bit to see how it goes?