Why are all major OS's (Windows, macOS, Linux, *BSD) all monolithic kernels? Why aren't there more microkernel operating systems, like for example Redox or Minix?
The NT kernel and XNU (macOS) are considered hybrid kernels. QNX, a microkernel, is absolutely everywhere (i.e., cars).
Performance of microkernels is or was a hotly debated topic back in the '90s; microkernels generally had lower performance than their monolithic counterparts. There was a famous argument comparing Linux (monolithic) to MINIX (micro) [0]. Wikipedia has simple explanations for the differences between hybrid, mono, and micro kernels that serve as a decent primer [1] and a visual that I find helpful [2].
Microkernels still have lower performance than their monolithic counterparts. It makes sense really: the major difference between the two is protection barriers between components. All else being equal, a system without those barriers is faster than one with them unless crossing those barriers has zero cost -- which it only really does in the case of proof-carrying code and similar software solutions, where the "barrier" is more of a guarantee that the subsystem behaves as it should.
A lot of microkernel research in the past focused on the "all else being equal" aspect, attempting to come up with innovative ways to reduce protection domain crossings in microkernels. For example, mapping graphics card memory or network device buffers directly into the address space of the client means that the hardware can deliver data directly to the client. However, monolithic kernels can also benefit from these sorts of innovations!
As to why consumer OSes are all monoliths (yes, this includes Darwin and NT -- "hybrid" is a marketing term as all the important stuff runs in a single kernel address space; see https://en.wikipedia.org/wiki/Hybrid_kernel): in consumer OSes, the 5% (or lower) performance hit of a microkernel is a big deal. In other spaces, such as embedded, the benefits of microkernels (reliability, security guarantees) are sometimes more important than raw performance.
It's simply not true that microkernels have lower performance. At least it can strongly depend on what you measure. There are tradeoffs, but high-level workflows can accomplish comparable performance. The problem is that sometimes requires rearchitecting software against alternative interfaces. It's becoming increasingly more common for very high performance applications to all directly to hardware and bypass the kernel altogether. Async io such as io_uring also further reduces disadvantages of a microkernel, especially on systems with many cores.
Shouldn't the microkernel architecture be capable of having fewer barriers in the fast path? e.g. you could have hardware like a NIC or GPU be capable of partitioning address spaces to have per-program command/response queues. Then the kernel asks on an administrative queue for a program's IO queue to be created, configures the memory controller (assuming an IOMMU) for the program to have those queues in its address space, and context switches to the program. While the program runs, there are zero barriers and it can simply talk to the hardware directly by writing into pcie space. Hardware knows what queues commands are coming from and can enforce whatever resource partitioning within firmware.
My understanding is that (perhaps except for virtualization/address space partitioning on the hardware device to be able to use it with many programs at once) this is approximately how/why user-mode networking is used for high performance today?
This is the basic idea behind the exokernel concept: have the kernel's only job be to enforce protection boundaries between processes, and then expose an interface to userspace that is identical to what the hardware exposes (eg. directly write to buffers and queues):
No production exokernels were built, but the concept lives on as virtualization. Most hypervisors (eg. Xen) work on a substantially similar principal: the hypervisor is responsible for securely multiplexing the hardware between guest OSes, and then the guest OS talks to an interface that basically looks like the hardware.
A step beyond this is to get rid of the guest OS and have application code talk directly to the hardware interface. This is a unikernel (or called a "libOS" in the original exokernel papers), and as you predict, unikernels running on a hypervisor are often faster than traditional monolithic kernel OSes. The main thing blocking their adoption is that they require significant rewrites to application-level code: most applications (and the libraries they depend on) generally assume POSIX syscalls are available and would need to be largely rewritten to work in terms of direct hardware access. You can rewrite POSIX as a library in userspace (this was the approach taken by the original exokernel research), but most of the performance gains come from bypassing inappropriate abstractions, so if you use the same abstractions you get basically the same performance.
in consumer OSes, the 5% (or lower) performance hit of a microkernel is a big deal
This does not feel like it should have been true for a long time. Computers are just stupidly fast now. In the 90s, sure, performance was way more important to prioritize, but I would love to see the needle swing the other way to getting a more secure and robust OS. My system already squanders so many resources on Electron JavaScript nonsense. Why not let the OS take up a few more cycles to give me hard security guarantees.
You can do that and people already do. The most microkernelly consumer OS is macOS/iOS and there you see a lot of code has been moved out of the kernel with time. Example: whilst APFS is in-kernel by default that isn't much security risk. More vulnerable components like FAT drivers have moved into user space. On iOS the networking stack also runs in user space for apps that use Apple's APIs!
So the whole TCP/IP stack is just a regular userspace library on that platform. Only the wifi driver runs in-kernel.
These platforms are made up of literally hundreds of Mach servers. Relatively little code runs in the kernel when you examine the structure of the whole OS. The kernel is really only running some hardware drivers where moving them to userspace is hard, and some basics like memory management, process scheduling, IPC and code signature verification. The kernel just isn't that big.
It's important to realize though that moving even more stuff to processes does not automatically improve security or availability. Imagine there's an RCE vuln in your root filesystem code. Being in a userspace server doesn't help you:
1. If you can control the FS you can make a root owned file appear anywhere and then just run it, or alter system configuration in any other way.
2. If you can crash the FS the core kernel can't easily recover without special cases because where would it restart the FS process from? If you say "initramfs" then you're back to having an FS in the kernel.
In practice there are lots of cases like that. Sometimes it's worth it - modern OS' can generally recover from a display server crash and run graphics mostly in user space. Sometimes it's not.
Finally, bear in mind that Linux is very insecure due to its huge feature set and reliance on C, but kernel exploits are often not the biggest security problem on other platforms. The most serious bugs are all in userspace already on most platforms.
Somebody tell that to my iPad which goes out to lunch for 30 seconds when I am browsing the web and always seems to be listening to the music in its head. Or the XBOX that takes 30 seconds to sorta kind boot but really 3 minutes for all the menus to load.
But not as the actual system OS. Minix is doing a very little, running on a little side processor that also does very little. It's not running on the main CPU, nor having to interact with the insane number of possible peripherals that real CPUs and OSes have to interact with, nor with real system loads, nor with many of the other constraints that real OSes have to deal with.
Yes, it's there. Yes, it's there in really massive numbers. But, compared to what the OSes are doing on the main CPU, Minix is doing a toy job. So I'm not sure that it counts as evidence for much of anything.
You necessarily cross from userland (end program) to OS to userland (driver) for most tasks that monokernels just do with the first userspace->OS transition.
There have been architectures specifically designed to support some form of IPC or other directly between processes without going through the kernel, and thus without having more overhead. But those are a bit esoteric.
The Mill is one, that has been in development for a while, but its company hasn't published much lately and its current status is a bit unclear.
It would have had something very similar to Spring/Solaris "Doors" in hardware, where the caller could have passed temporary permissions to memory ranges. A "kernel" would have been a process like any other, just with more permissions.
There's no way a 5% performance difference is the reason. These OSes were designed in an era where you could get a 5% boost just by waiting a month.
I think the real reason is they were also designed at a time when security was not as advanced as it is now, especially for Linux, and microkernels are more secure but also harder to write.
Whatever you want to call it, NT is neither a pure microkernel nor a pure monolithic kernel. Linus' opinion of the term 'hybrid' being a marketing term is great and all, but it's just an opinion.
You could call NT a 'modified microkernel implementing monolithic kernel concepts', if you wish. The word 'hybrid' is much shorter, though.
> In 2017, it was revealed that Intel was running MINIX inside the Management Engine, a separate processor incorporated in Intel processor chipsets since 2008. As a response to this, Tanenbaum wrote an open letter to Intel claiming MINIX to be "the most widely used computer operating system in the world".[17]
Hilarious.
I only wish I had a bucket of popcorn before I began reading this.
There have been attempts at using QNX for a mainstream OS though, neither that gained major success but not because of lack of technical merit.
In the mid 1980's, the ICON microcomputer system, perhaps known mostly for being used in Canadian schools.
In the early '00s, QNX got jealous of Linux's success and started opening it up to try to attract app developers from the open source community.. but closed down the program before it could gain traction.
In the early '10s, it was bought by Blackberry and used for the OS of a new wave of Blackberry smartphones and a tablet.
QNX is promoted as a microkernel, but I'm skeptical. Microkernel doesn't just mean that we have modules that have their own threads. It refers to actually moving kernel functionality outside of the protected kernel space: device drivers, file systems, protocol stacks and such are in userland.
Definitely read up on the Torvalds/Tanenbaum debate as there are lots of moving pieces and interesting theories.
My opinion summed up ridiculously concisely is that the reasons are largely accidents of timing (i.e. there was room in the market for new entrants), mixed with trivial-at-the-time but high-impact choices. Had Tanenbaum been permitted by his publisher to give away copies of minix freely, Linux may never have been started at all. Had Tanenbaum chose raw performance over teachability (the kernel was a teaching tool after all), it may have made a difference. (warning: this part is controversial) There's also a lot of question about whether the GPL licensing kept Linux relevant, or if it was largely inconsequential. My opinion is that GPL made a big difference. Had the licensing of Minix been GPL flavored, it probably wouldn't have been used by companies like Intel for the Management Engine, but there might have been enough "forced sharing" to keep it relevant. Impossible to say for sure, but that's my two cents.
Linux wouldn't really exist today if it wasn't for GNU Hurd being a microkernel. It took so damn long for Hurd to become stable that nobody wanted to use it. But people did want to use the GNU tools. So Linus made the Linux kernel a simple monolith, shipped it quickly, integrated patches quickly, and everyone started using it. By the time Hurd was stable, Linux was popular. So microkernels are hard and monoliths are easier, and the first one to the party tends to stick around the longest.
Based on your comment and this question [1] I wonder how well GNU Hurd runs the open source stack and what problems you will find in the road (e.g. GPU support).
I really like the approach of separating, in some way, the kernel, from the user space and interchange them but why you would do that, except for playing and research, if the kernel doesn't give you an advantage and it just an alternative?
On the software side, it's passable; as that post notes, there's a Debian spin on HURD that's basically functional.
In practice, though, GPUs are the least of its concerns; AFAIK, HURD still doesn't support USB:(
> I really like the approach of separating, in some way, the kernel, from the user space and interchange them but why you would do that, except for playing and research, if the kernel doesn't give you an advantage and it just an alternative?
Well I think a lot of it is that we thought it would be easier; in theory, separating concerns and putting drivers in userspace sounds like it should make it a lot easier to write the OS. That didn't really turn out, but it seemed like a good idea at the time. On the more practical side, microkernels can have security and reliability benefits (if drivers run in userspace, they have less access to exploit, and crashing a driver doesn't crash the whole machine). I mean, diversity is also useful for its own sake, but there are more immediate benefits.
It's not really the microkernel per se that delayed GNU/Hurd so much. From the beginning the Hurd project had a more ambitious interpretation of the microkernel paradigm than other microkernel operating systems (e.g. Minix), and this shifted the project from engineering to research, leading to never-ending architecture changes and even wholesale microkernel replacements: https://www.gnu.org/software/hurd/hurd/ng.html
Very oversimplified answer: Microkernels still have a performance hit, end-users care more about performance than stability/security (at least at the ratio/margin in question), therefore we use the faster monolithic kernels for most user-visible systems, with carve outs where the performance hit isn't so bad (hence NT/Darwin really being more hybrid now, and even Linux can do some drivers in userspace). As other comments note, this only applies to places where performance matters; lots of embedded systems do in fact care more about reliability than performance so the outcome is different.
Which in a nutshell comes down to Linus's view that producing a system that meets current needs (for example by offering a simple API) and is reasonably performant -- even if it ran on but a single architecture such as the i386 -- was more promising than a design offering "theoretical" benefits (such as portability) but which either didn't deliver the goods today or just wasn't reasonably performant.
This is a vast simplification of a much broader set of issues but if one digs into the notes of why subsequent projects (e.g. Windows NT) moved away from microkernel designs, or the roughly analogous microservices debate of the past decade -- one often finds echoes of the same basic considerations.
Linux has more microkernel features than you'd think. You can run all of networking, filesystems, HID and more in user space with BPF/Fuse. What else is left?
(That's a feature for helping wheelchair-type passengers board at ground-level without assistance—just to explain for those who live in places without public transit).
Thanks for the explanation. I live in a place with lots of public transit but no suspension in any passenger bus. Fortunately I've been to the US before so I now know what it is.
Well, what are we missing if networking, file systems and human IO are now run as user space servers? Process management? Graphics (ignoring X)? What low-level hardware interaction can't be done microkernel style?
It's a bad analogy unless the button makes the bus change Transformers style into a completely different car.
Your "userspace filesystem implementation" is still entirely dependent on the giant VFS layer of the kernel. The situation is similar for networking. And a large portion of human I/O still depends on a very large kernel surface as well. That's not even beginning to touch on pretty much all things related to virtual memory.
Just because you've delegated some small parts into userspace, does not mean that you don't still have a massive monolithic kernel with metric tons of infrastructure and subsystems all running in the same kernel address space, oftentimes not even as dedicated threads.
A monolithic kernel is a tiny kernel that does not do much more than message passing. Linux is very far away from that, your "userspace servers" for FUSE and similar things are better called "delegates" for subsystems that still reside in the kernel itself.
> It's a bad analogy unless the button makes the bus change Transformers style into a completely different car.
> Just because you've delegated some small parts into userspace, does not mean that you don't still have a massive monolithic kernel with metric tons of infrastructure and subsystems all running in the same kernel address space, oftentimes not even as dedicated threads.
That's up to you to keep around. No need to compile in subsystems and drivers you don't need. HID is pushed userspace by HID-BPF and it works great. USB, I2C, SPI can all be handled by direct messages to the device.
These objections are pedantry around what exactly is micro about a microkernel. UIO lets you drive any hardware via userspace memory maps, it's just usually easier to slap it into a pre-built kernel subsystem more than any need for code to be in kernel mode.
> A monolithic [sic] kernel is a tiny kernel that does not do much more than message passing. Linux is very far away from that, your "userspace servers" for FUSE and similar things are better called "delegates" for subsystems that still reside in the kernel itself.
Your message passing is my delegation through, say, netlink. Perhaps you are describing an exokernel concept where only the barest minimum is run in kernel mode? Mach runs a lot more in kernel mode than necessary, even L4 isn't a "true" microkernel if you are ultra-pedantic and run on processors with, say, userspace interrupts.
I am not familiar with this project. It looks to be a VFS-like framework for userspace? If so, I don't see how that changes the nature of a kernel. I can implement any amount of kernel-like features on top of any operating system, provided I have Turing completeness.
By that argument, I can take pre-NT enhanced mode Windows, arguably one of the least microkernel kernels there is (AFAIK it even has large part of its UI system running in kernel space), run an L4 kernel within it as a userspace application, and declare that "Windows 3.11 is now a microkernel"?
As long as this SPDK thing does not rid me of VFS, it's just adding stuff in userspace?
> That's up to you to keep around. No need to compile in subsystems and drivers you don't need.
I genuinely did not follow Linux kernel development for quite a long time (as opposed to other OSes, like OpenBSD for example). Are you saying that nowadays (or maybe back then even), I can compile out VFS, the POSIX layer, the VM layer, kernel memory allocators?
If so, that's indeed a big step towards microkernel-ness!
> These objections are pedantry around what exactly is micro about a microkernel.
You're saying I'm pedantic about what is a microkernel, I'm saying your definition of "microkernel" seems surprisingly broad, and question the merit of the term under that definition.
According to you, where does a microkernel stop, and a monolithic kernel start, then?
> Your message passing is my delegation through, say, netlink.
netlink is not only one of many communication paths in Linux, it isn't even a raw message passing mechanism in the microkernel sense! It's built on top of POSIX and the socket layer, which are surfaced through many individual system calls into the kernel, and whose implementation is a pretty thick sandwich to get down to the actual mechanism that passes the message, i.e. that implements how the actual data is made available from one address space to another (zero-copy or not).
This is the actual low level mechanism, on top of which POSIX and pretty much everything else is built, outside of the microkernel. So it's actually quite the opposite of netlink!
> Perhaps you are describing an exokernel concept where only the barest minimum is run in kernel mode?
Liedtke's Minimality Principle states: "A concept is tolerated inside the microkernel only if moving it outside the kernel, i.e., permitting competing implementations, would prevent the implementation of the system's required functionality."
So it seems that your "exokernel" definition matches my "microkernel" definition.
Now, that definition represents an ideal that may not always be achieved in practive, but even then, the word "micro" in "microkernel" alone indicates that what should run in kernel mode should, at the very least, be extremely small. For my senses, I don't think "all of POSIX and VFS" is cutting it for that.
> even L4 isn't a "true" microkernel if you are ultra-pedantic and run on processors with, say, userspace interrupts.
I am actually open on what the "proper" definition of a microkernel is, but if the current state of the Linux kernel is included in that, and again if my present understanding of Linux is accurate and up to date (i.e. POSIX, VFS, allocators, all of the vm layer, and many many more things are still integral and inseparable parts running in kernel mode), i.e. if the term "microkernel" is not sufficient to separate such a kernel from QNX's Nucleus, or L4, then that term strikes me as rather useless.
FWIW, I don't think I have ever seen any Linux kernel maintainer, including Linus, referring to their kernel as a microkernel. I have seen the exact opposite in the famous debate with Tanenbaum, but that was decades ago, so I have to be open to the possibility that the shape of the Linux kernel may have changed significantly since then.
> A sports car is a car designed with an emphasis on dynamic performance, such as handling, acceleration, top speed, the thrill of driving, and racing capability.
How would lowering suspension turn a passenger bus to a sports car?
New OSes that have come out are pretty much universally microkernels. Fuchsia from Google is on a lot of their devices, and is a microkernel. SeL4 and QNX are microkernels for security and safety critical devices. I believe that Firecracker from AWS is also sort of microkernel-like (but pretends to be Linux). If you are building the device, the kernel, and the software, chances are that you are using a microkernel in 2024.
Windows and the Unix OSes just have a lot more market penetration, strong network effects, and a big first-mover advantage. That means that when you are buying your OS or your hardware or your software, you're probably stuck with a monokernel.
Lots and lots of home users care more about the few % of performance than the nebulous "extra security".
I have friends who use their desktop for gaming only, literally nothing else, I guarantee they don't care about the extra security a microkernel claims to offer.
Nobody actually wants microkernels. Remember that the microkernel design is just a pessimistic mitigation. It assumes code will be crashy and full of exploits forever, and that it's worth significantly complicating the design as well as sacrificing performance to try and mitigate that. If you're making an OS you could invest resources into micro-kernelling everything and then trying to resolve the many hard problems and bugs that mitigation itself creates, or you could just .... fix the bugs! Kernels aren't infinitely large and the latter is actually much preferable if you can do it.
Some kinds of code are inherently in the core failure domain and trying to use restartable processes for them is impossible. For example if the code configuring your PCI controller crashes half way through, well, you need to reboot. You can't just restart the driver because you have no idea what state the hardware is in. A reboot gets you back into a known state, a server restart doesn't. Likewise if your root filesystem server segfaults, you can't restart it because your process start code is going to involve sending RPCs to the filesystem server so it'd just deadlock.
Finally, it's a spectrum anyway. Microkernel vs monolithic is not a hard divide and code moves in and out of those kernels as time and hardware changes. The graphics stack on Windows NT started out of kernel, moved into the kernel, then moved back out again. In all OS' the bulk of the code resides in userspace libraries and in servers connected via IPC.
Because microkernel was born in an era when cpu cycles were precious and albeit minimal, the difference in performance would be noticeable. Also, back then there were no security reasons to choose one over another; those were the days of NNTP and unencrypted email, and the web didn't even exist. I can't comment about other OSes, but in the case of Linux, when microkernels became stable enough, Linux had already taken over and was already running from supercomputers down to embedded systems (also 8088 based ancient hardware if one also counts ELKS). As of today, in my opinion, the biggest obstacle are device drivers; that's the biggest battleground that determines the success or failure of an OS. Linux runs pretty much everywhere and where hardware manufacturers stubbornly refuse to document their hardware, there are thousands of developers around the world spending time and money to reverse engineer closed drivers so that Linux can support more hardware. Of course once they're written they can be ported to other OSes, but that requires more time and more people devoted to the job.
In the world of Linux, "micro-kernel-like things" are done when they are beneficial. An example of this is FUSE: filesystems in user space. There is a benefit to being able to run a filesystem in its own address space as a user process, so it is done.
Also the model of a Unix kernel with services (daemons) in user space is kind of similar to the microkernel model. The graphical desktop is not in the kernel, the mail server isn't in the kernel, crond isn't in the kernel, the web server isn't in the kernel, the database server isn't in the kernel ... and maybe that's as close as we need to get to the microkernel.
Speaking of web servers in user space: at least for serving a static page, it's faster for that to be inside the monolithic kernel, where it can access the protocol stack and filesystem code without crossing a protection boundary.
Over the history of Linux, we have seen experimentation both with moving kernel things into user space (like with FUSE) as well as user things in to the kernel (TUX server, now evidently unmaintained).
Because once something works it is hard to start over from scratch and also hard to do a major refactor. It can be done but few can dedicate the time needed and so you stick with what is even if not ideal.
Also, it was never really clear that, in the end, a microkernel would offer significant practical benefits over what could be accomplished (with less work) within one of the established non-microkernel OSs.
Had to scroll a long way to find this, I suspect this is far more important than any technical issue.
Having an "owner" is a strong incentive/coordination point to get stuff done. You need the right owner, but the 95% of projects that don't get it right, we don't hear about.
We hear all the time about how code structure mirrors org structure. A distributed project encourages fiefdoms, a centralized one asks for a taskmaster with final say.
And what prevents a microkernel from having the exact same owners as a monolithic kernel, working on the exact same things?
This isn't web development, where "microservices" came up as a way to distribute complex software across stakeholders. There are very hard purely technical reasons for (or against!) microkernels, and the majority of microkernels (if not all) are still released and distributed in a "monolithic" model, i.e. an update distributes all components of it (modulo delta updates, which is also just a technicality).
> And what prevents a microkernel from having the exact same owners as a monolithic kernel, working on the exact same things?
Nothing inherent to the software is preventing anything. You could be right about the technical justifications. But OP's question wasn't "which is better?" it was "why?"
> A distributed project encourages fiefdoms, a centralized one asks for a taskmaster with final say.
What does the distinction between microkernel and monolithic kernel have to do with whether the project is “distributed”, or whether it is a “fiefdom”?
Nonsense. The same set of people working on a monolithic kernel could work on a microkernel instead. It’s a purely technical decision.
What you say is akin to saying that you don’t want to divide the storage in your basement into multiple crates instead of one large one, because you somehow would need multiple people to manage and access each individual crate?
My hunch is that you’re somehow applying micro services in web development, and their motivation for existing, to OS design.
This used to be a site for great technical discussion.
I don’t understand your very premise: Why does a monolithic kernel imply “central control” when developing, and a microkernel not? How does one or the other change the “politics” of the kernel? Can you state what you think the difference between a monolithic and a microkernel actually is?
The "politics" isn't a technical paradigm, it's a human one. I'm not arguing the merits of one over the other, I'm offering an answer to OP's question.
Again, what is the difference between a microkernel and a monolithic kernel, and why does it influence the politics of development? And, again, why does a monolithic kernel imply “central control” in development, over a microkernel?
No, the difference is in what parts of the OS are in what privilege level and address space, and how they communicate with each other. It has nothing to do with the shape of teams building them. If someone is building a filesystem or a network protocol for the system, then the difference between that person implementing a server for a microkernel or a kernel module for a monolithic kernel is purely a low-level-detail technical one.
I think we're talking past each other. You want to discuss architecture and that's fine, super.
I'm merely offering a different explanation for why software, which is presently built by humans, might express different configurations based on that fact. It's not a qualitative statement as to the merits of one over the other.
For one thing, writing things in a microkernel are far more complex. In theory the isolation can mean lower impact of bugs and security issues; but in practice, the complexity means more bugs which are harder to debug. That's why you don't really see microkernels outside of embedded use cases -- the lower functionality requirement makes the complexity manageable.
You can write a rocket OS as a "proper" microkernel, but there's no way you could write a full-blown Windows OS as a "proper" microkernel.
That said, Windows or Linux can take leaves out of the microkernel playbook and apply them judiciously: KVM's architecture is arguably an example of this, where the core kernel does only the minimum necessary, and everything else is pushed to the user-mode component (QEMU, Firecracker, etc).
Is Linux really a monolithic kernel? I mean yeah for most use cases such as desktops and servers it is but there's nothing preventing you from disabling most of its features and drivers and keeping a very minimal core (I'm sure lots of embedded Linux does this) and you can, right now, make it act as a microkernel by putting any component in userspace, mounting filesystems and devices via FUSE and networks via TUN, at its current state.
Now the question becomes why these components are built in the kernel and not in userspace? The answer is clear for each individual component. See how the in-tree NTFS driver eventually replaces NTFS-3g. Basically when an in-tree solution exists it just gets preferred over userspace solutions because of performance and reliability etc.
Making a monolithic kernel slightly smaller does not make it a microkernel. And those userspace fs and tun drivers still build upon VFS and an entire network stack as part of the monolithic kernel.
Again, absolute nonsense. Microkernels were designed for entirely different reasons than microservices. There are hard technical reasons for and against them, and most, if not all, microkernel OSes are still distributed in a rather monolithic model, not piecewise.
Where did I mention microservices? How does the fact current microkernel OSes are being distributed using a monolithic model imply my point is nonsense?
A real microkernel OS with stable interfaces would mean its developers do not want control of all the kernel-like servers, and allow even basic users to easily install and use many alternative user servers, as opposed to Linux kernel services sanctioned and controlled by the Linux distribution kernel maintainers.
Those things are completely orthogonal. A microkernel can arbitrarily restrict what user servers are viable (for example just the ones it ships with), just like a monolithic kernel can arbitrarily restrict what loadable kernel modules are viable (for example just the ones it ships with).
A compiled microkernel can restrict, I agree. But if you want to restrict, why would you do a microkernel. It's much easier to justify with a monolith.
One big point of making a microkernel as opposed to making a monolith is that you want to give other developers more freedom to develop, distribute, fix bugs on their own time schedule, while keeping compatibility with new kernels easily. In other words, not wanting to control what and when they do, and what users run on the kernel.
Monolithic kernel like Linux, with its constant stream of little changes in interfaces, creates problems for developers of modules, and this leads to selection - those who keep up and satisfy the kernel requirements get in, those that don't keep up or do not satisfy requirements, can't get in, and are degraded to developing against some old kernel version. This is a kind of control.
I’m going to venture a guess that you haven’t ever applied a single patch to any existing operating system, and that your knowledge of operating systems is pretty much based entirely on your experience as a user of them.
Performance of microkernels is or was a hotly debated topic back in the '90s; microkernels generally had lower performance than their monolithic counterparts. There was a famous argument comparing Linux (monolithic) to MINIX (micro) [0]. Wikipedia has simple explanations for the differences between hybrid, mono, and micro kernels that serve as a decent primer [1] and a visual that I find helpful [2].
[0] https://en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_deb...
[1] https://en.wikipedia.org/wiki/Kernel_(operating_system)
[2] https://en.wikipedia.org/wiki/Hybrid_kernel#/media/File:OS-s...