In fact, micro kernels have a lot of issues and limit the possibilities of what an OS can do! One of the most important issues is they prevents resource sharing in a rich and efficient way between the components of the kernel. They make building rich relationships between kernel data structures and kernel subsystems very messy, complicated, impracticable and very inefficient.
Micro kernels are delusional and people should stop implicitly assuming their superiority.
Rust's memory model largely makes those isolated address spaces unnecessary, and sending a message at runtime basically amounts to copying a pointer. So, with these performance issues resolved, I think it makes sense to look at microkernels again. The reasons why Linus was opposed to writing Linux as a microkernel in the 90's don't necessarily still apply now in 2021.
There may some things the Linux kernel does that can't be efficiently expressed using a message-passing style, but I don't know if that's actually true or not.
I think you're confusing several concepts. Rust's "memory model" is the C++11 memory model. Maybe you meant the borrow checker and the distinction between shared and exclusive references? Yes, those make it much harder to accidentally screw up other parts of your address space, but it's downright trivial to do it on purpose – you just need an unsafe block and std::ptr::write.
There's nothing about Rust that could replace isolated address spaces. Rust is typically compiled to native machine instructions, there's no sandbox or virtual machine that will protect different modules from each other.
I'm also imagining a usage model where all the various components of the microkernel come from the same place and have passed various minimum standards like "doesn't have any unsafe blocks". If some program really needs an unsafe block to do something, then that goes into a (hopefully small) library of heavily-scrutinized functions that do dangerous things but expose safe interfaces.
If we compare with the Linux kernel: in Linux, any part of the kernel can clobber memory in any other part; there's no protection at all. Users generally accept that because the Linux kernel is a pretty well-run project, but still bugs slip in from time to time. If instead you imagine a system where the compiler simply doesn't allow one part of the kernel to clobber memory that belongs to some other part, that would be a significant improvement over what Linux offers.
Anyways, security mechanisms don't necessarily have to be enforced at run-time if they can be enforced at compile-time. That assumes you compile the code yourself with a trusted compiler, or you get the binaries from a trusted source. (Though unfortunately Spectre has become a big problem for compiler-enforced data isolation within one big shared address space; I'm not sure whether compilers these days can do code generation in such a way that it doesn't suffer from sidechannel attacks, or if for the foreseeable future it's just something that software developers have to be wary of.)
In theory you might eventually be able to run device drivers from random people or run arbitrary applications in the same address space as the kernel, but that would require a lot of faith in the compiler to reject anything that could be a security hole. It's an interesting model, though; a pure unikernel approach everything shares the same page tables and there's no need to swap them in or out when context switches happen. And invoking a system call can be as cheap as executing an ordinary function. It might even be inlined by the compiler.
Device drivers make up the largest part of the Linux kernel, and they would by necessity contain lots of unsafe blocks – the compiler can't reason about the interaction with some device. This is typically different from device to device, and there's no way this could be separated into a small library or module.
Look, I agree that a kernel written in Rust could be much safer than one written in C, and even those instances of 'unsafe' blocks would be easier to audit than C's "everything is unsafe". But it still couldn't replace all the advantages you get from micro-kernels with separate address spaces.
For example, it's impossible in Rust to safely unload a dynamically loaded library. The reason for this is, that such a library could contain static data, like string literals, which are of type &'static str. Passing a 'static reference from the library to the program doesn't require 'unsafe', but will leave a dangling reference when you unload the library. Of course, the unloading operation is itself 'unsafe', but that doesn't help you prevent, locate, or track the transfer of a 'static reference.
Another advantage is that there is no such thing as a kernel crash, worst case you get a device driver that needs restarting. The whole loadable module model is broken by design and replicating it in Rust isn't going to solve that particular problem (and it isn't one that Rust is trying to solve).
The concept is interesting (if maybe untested) it allows to have explicit opt-in sharing while blocking accidental sharing
Rust's compile time checks cannot replace the MMU. There were experimental SAS (single address space) operating systems which didn't depend on the MMU for protection, but they used "managed" languages, i.e., all code was executed in a sandboxed JIT.
What about that WiFi driver with 10,000s of lines of code? Are you absolutely sure there isn't some code in it that accidentally or purposefully leaks the rest of your kernel data structures to the outside world? With drivers in their own isolated address space, you wouldn't have to be.
Can't find it right now, but I recall reading they implemented a network driver with minimal overhead compared to a traditional OS. While they used message passing, a lot of overhead could be eliminated due to the assumptions of safe code.
[1]: https://en.wikipedia.org/wiki/Singularity_%28operating_syste...
But this does argue against message passing, since such systems preferentially try to use messages over sharing whenever it's possible.
There have been several other "real micro kernel based OS based on a message passing core", and they too, by almost any metric, have been a failure.
Process scheduling in Linux in 2021 is far, far ahead of anything in any other OS, ukernel or MP-based. The idea that there hasn't been progress in this area is really completely absurd. In fact, the general idea that Linux follows "the now 50 year old Unix architecture" is also pushing the boundaries quite a lot.
But you're right, QnX is the one (probably the only?) micro-kernel that has seen widespread adoption. Almost all of it has been in the context of embedded systems, which doesn't invalidate the substantial success, but it does leave QnX as the exception that proves the rule. It also leaves QnX as yet another example of the general failure of microkernels as general purpose computing platforms. QnX design is excellent for the contexts where it is deployed, but there's a reason you don't run it on PCs, tablets, data crunchers, smartphones and many other sorts of computing contexts.
I used it daily on my PC for years and it was hands down the best environment I've used with distance (mostly compared to IRIX, Windows and Linux). Super responsive, never locks up, no weird delays it just works, 24x7, year after year. The whole throughput argument never worked anyway, that was just Linus talking about something that he didn't have direct experience with, it's latency that is far more important than raw throughput in interactive computing because interactive computing is a real time task.
BeOS wasn't half bad. The failure was probably mostly commercial. It is true that they moved their networking stack into the kernel, but it's not entirely clear to me that they had to do that, it was just the most expedient way to get acceptable performance and stability given the (programmer-time) resourcing constraints of the project.
Fair point. You could probably say this of other attempted microkernels too, to be even fairer. But that doesn't really change the fundamental point that just cooking up "a better OS design" doesn't lead to it being successful. There's a lot more in play that "mere quality".
you did say "by almost any metric".
https://en.wikipedia.org/wiki/QNX
https://en.wikipedia.org/wiki/Fuchsia_(operating_system)
https://lobste.rs/s/p8bizb/getting_know_fuchsia_google_s_ope...
I would love to see a solid implementation of a real micro kernel based OS based on a message passing core in Rust to become a viable alternative to the now 50 year old Unix architecture. This would give us a possibility of some real progress on the security and process scheduling front, both of which are severely lacking in the Unix model.