Back to News
Advertisement
Advertisement

⚡ Community Insights

Discussion Sentiment

50% Positive

Analyzed from 746 words in the discussion.

Trending Topics

#microkernel#linux#device#peripherals#processes#message#system#need#context#microkernels

Discussion (3 Comments)Read Original on HackerNews

vsgherzi•about 5 hours ago
Errors in the code potentially mean killing the liveness of the system or worse corrupting the system in a poor state. Think the networking stack getting corrupted because of bad business logic.

Also very hard to debug

vsgherzi•about 3 hours ago
Edit omg… I was thinking of unikernels…
theamk•about 5 hours ago
> The overhead was too high because computers in the 80s didn't have a way for a userspace process to directly access a particular hardware device.

Eh, no, author mixed things up. To access a hardware device, you need ioperm, which is at least 20 years old. (Well, not today, but it was sufficient back then...). IOMMU is completely optional.

The microkernel overhead was too high because any operation (even the one that does not need access to hardware, like reading file from file cache) required a context switch. This does not change with IOMMU. And while having multiple cores helps, you are trading context switch to intra-core cache invalidation and extra scheduling overhead (because no modern system can just have a single core spinning forever).

adrian_b•27 minutes ago
Ioperm, which was introduced by 80386 in 1985, is useful only for a few legacy peripherals.

It allows the operating system to allocate peripherals mapped in the special I/O address space to dedicated device driver processes. For example it could allocate the real-time clock to such a process and a serial UART interface to another process.

Most modern peripherals are memory-mapped. However, you are right that even on the older systems without an IOMMU, the operating system could allocate peripherals to separate device driver processes, using the standard CPU MMU and mapping the peripherals using appropriate page attributes, e.g. as uncacheable memory regions.

The IOMMU is not needed to protect the OS and the processes between themselves, but it is needed to protect both the OS and the processes from rogue peripherals. This is needed regardless if the kernel is monolithic or a microkernel.

The microkernel overhead in the old microkernels, like Mach and all those inspired by it, was indeed too high due to context switches, but that has nothing to do with microkernels but those microkernels just implemented an extremely inefficient method of IPC, which unfortunately has tarnished the reputation of microkernels.

The only right form of IPC does not use any context changes, i.e. it uses message queues located in shared memory pages, with zero copying and no context changes, which is much faster than the traditional syscalls used with monolithic kernels.

In TFA there is another thing with which I do not agree, it is said that message queues need atomic CAS (compare-and-swap, a.k.a. compare-and-exchange in Intel parlance).

In my opinion, using CAS for implementing message queues is a big mistake, because this instruction is non-deterministic and the execution time for any program that uses CAS is unbounded for the worst case.

One-to-one message queues do not need any atomic instructions, they just need store-release instructions and either wait-for-not-equal loops when the waiting times are expected to be short or futex_wait (or similar) syscalls when the waiting times are expected to be long.

Waiting for (multiple) events is one of the principal functions that must be implemented by a microkernel for enabling interprocess communication, together with a memory mapping API. IPC per se must not be implemented by the microkernel, but by user-space libraries.

The message queues that are many-to-one, one-to-many or many-to-many, can use the atomic fetch-and-add instruction (LOCK XADD on x86-64), to dynamically partition the queue, allowing the concurrent insertion and extraction of data into/from the queue by all communicating processes. In this case, only the updating of the queue pointers is serialized, resulting in very low overheads for the communication through the message queue, even in cases of high contention.

While I agree with you that TFA is incorrect in some details, I agree with the general idea that today one could implement microkernels that would be simultaneously faster and safer and easier to maintain than a monolithic kernel like Linux.

Nonetheless, the chances for such a microkernel to appear and to be successful are very low.

The reason is that the only way to be successful would be to implement a very easy transition to it from one of the popular OSes, e.g. from Linux.

This means that it would have to also implement a syscall interface completely compatible with that of Linux, to allow running unmodified legacy programs, and also a device driver API compatible to that of Linux, to allow the reuse of the existing device drivers.

Probably the easiest way to do this would be to start from Xen, still using the root Xen domain with a Linux kernel that manages the I/O, and running legacy Linux applications in virtual machines.

From this, another special domain with the new microkernel should be added, and then the peripheral handling should be migrated gradually from the Xen Dom0 Linux to the microkernel with its associated device driver processes, starting with those more important, i.e. time, keyboard & graphic pointer, GPU, NVMe, Ethernet, USB.

In parallel with migrating peripherals to the microkernel, user applications should be migrated gradually, to use the new I/O IPC instead of the Linux syscalls.

Only such a gradual evolution could succeed. Otherwise, a nice microkernel with which you cannot run any useful application would fail, like the many attempts of creating better operating systems that have failed in the past, even when they were backed by huge companies, like IBM OS/2.