Keeping on writing the concepts and design chapter… pretty boring one, hope it gets more exciting…
Kernel Classification
Kernels can be classified into four categories: monolithic kernels, microkernels, hybrid kernels and exokernels. This classification differentiates
the way the kernel is internally organized, and how each part interacts. There has been a lot of controversy on which is the best way to design a kernel,
each kind of kernel has it’s advantages and disadvantages, and all have been proved to be valid.
UserSpace vs. KernelSpace
This topic will be treated more deeply on following chapters, but some knowledge is required before proceeding. On all systems the kernel must be able
to guarantee stability. If an application crashes, it can not make the whole system go down. As the kernel is always resident into memory, we have to
guarantee that no user application will alter the memory the kernel is using.
To accomplish this protection, processors provide us with a hardware protection method. The processor can enter into different states( rings), each
having different access privileges. This way we can separate a running space for the kernel and another for the user applications. The kernel has access to all
memory and I/O devices, but when we are running in userspace we can only access to “our” memory region and the I/O that the kernel has made availible
to userspace.
The switch between kernelspace and userspace is done via interrupts or traps, often called system calls. A userspace can issue a system call, then the system
enter into kernelspace, validates the call and proceeds to execution of it.
It is important to notice which parts of the operating system are running under kernelspace as this is the main difference between different kernels
and an issue of performance, as switching from kernelspace to userspace or vice-verse has a great performance penalty.
Kernelspace is also called supervisor mode, protected mode or ring0.
Monolithic Kernel
A monolithic kernel includes all of its services inside the kernel, everything runs in kernelspace this includes the core kernel services and the drivers.
This way the number of switches between userspace and kernelspace is the minimum, thus theoretically increassing the performance of the system.
This does not mean that all supported drivers have to be on memory at the startup time, but if we need some driver, it will have to be dynamically loaded
so as to be able to use it, this is often called kernel modules.
A main issue with monolithic kernel is portability, being hard to achieve as each part of the code has to be rewritten for each specific architecture,
the monolithic OS is not portable. But if we take specific examples of monolithic kernels, we will see that portability is achieved through pre-processor
directives which specify which part of the code are to be compiled for which hardware.
A highly criticized problem of monolithic kernel is the space they need to run, as every service has to be loaded into memory, this can result on big
kernels, this can be partially solved by loading dynamically the needed parts of the kernel, but once loaded they reside in memory and as long as
we need them they can not be unloaded.
The main advantage of monolithic kernels is said to be the ease of development and performance, which is supposed to be better, at least on X86 which has
a great penalty for context switching.
The philosophy behind monolithic kernels is that all code inside the kernel must be correct, as if any part of the kernel fails the whole system can crash, for
example, if a device driver is badly coded it should not be included and the device will not have support.
Microkernel
The microkernel approach consists in defining a very simple abstraction over the hardware, with a minimal set of primitives to implement the core services
of the operating system. This consists on running the minimum necessary services under protected mode, and the rest of the services run as process
under userspace, so what is left to the kernel are the basic services like memory allocation, scheduling and messaging.
Microkernel are supposed to be more responsive as much of the tasks can be interrupted anytime ( preemptive userspace ). There is a benefit for multi-processor
and distributed systems, as it is easier to separate each service, but a drawback is the number of context switches required, which tend to be much
higher than those of monolithic kernels.
In contrast to monolithic kernel, microkernels seek to be platform independent, only the part which communicates directly to the hardware has to be
rewritten for every system, this part is called HAL\footnote{Hardware Abstraction Layer}. All the services do not need to be rewritten as they rely on the
standard API of the HAL.
Hybrid kernels
Hybrid kernel are a mixture of monolithic kerels and monolithic kernels, they try to get the best of each one. The idea is having some non-essential code
in kernelspace. Most modern operating systems fall into this category. It has to be clear the difference between monolithic kernel that load modules dynamically and
hybrid kernel, hybrid still have services as process while have some non indispensable code inside the kernel, which helps improve the performance of the
whole system.
Exokernels
This approach to kernel design is completely different from previous architectures. The idea is that the developer has complete control of the hardware. The
kernel is really minimal, it just contains the protection mechanisms and the multiplexing of resources. Classic kernels hide the hardware behind some kind
of abstraction layer, so after allocating some space, one can not where this space physically resides.
The main purpose of exokernels is that an application can request any physical resource and the kernel just assures that the resource is free and lets the
application access to it.
The rest of the functions are provided by a library operating system. This library provides the interface for application programmers as if they were using
a full OS.
Theoretically it is possible to run many operating systems on top of an exokernel, giving each opertaing system different resource capabilities.
While Monolithic and Microkernel are well defined terms, the exokernels have many slightly different variants such as, nanokernel, picokernel, cache kernel,
virtualizing kernel, etc…