Comment by afr0ck
5 years ago
Why do people implicitly assume that micro kernels are the best OS design?
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.
Historically, one of the main arguments against microkernels is that having a kernel that's broken up into a lot of threads that each have their own hardware-enforced memory protection and use message passing to communicate with each other is dreadfully inefficient. All those context switches are expensive, and copying all that data around when you send messages is expensive.
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.
> Rust's memory model largely makes those isolated address spaces unnecessary,
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 meant the ownership model.
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.
2 replies →
The point was to use compile-time checks instead of a MMU to separate kernel services.
The concept is interesting (if maybe untested) it allows to have explicit opt-in sharing while blocking accidental sharing
1 reply →
I think we have to assume that people aren't putting malicious code into the kernel, don't we?
4 replies →
This is a limitation of the memory model, not the microkernel. If you had a single hardware-protected address space, kernel modules could share resources freely.
But this does argue against message passing, since such systems preferentially try to use messages over sharing whenever it's possible.
Message passing at first seems interesting and neat and useful. It is for some cases. But it comes at a cost of complexity and latency.