Modular core versus microkernel / monolithic core

I am a C programmer and new to Linux kernel programming. I could find that there are 3 types of core of a monolithic, micro and modular core. While googling I could find some kind of site, they say that linux has a monolithic kernel (in a stack overflow), and some others talk about a microkernel, while others talk about a hybrid kernel. Therefore, I am completely confused reading the modular concept, which says that a new module for the driver can be added without recompiling the kernel, which contradicts my assumption that Linux uses a monolithic kernel. a monolithic kernel works in a single address space and as separate processes , this also confuses, if so

+5
source share
3 answers

Before you try to understand these differences, you first need to understand other concepts:

1. Modular programming.

The module is a functionally complete part of the program. A module usually has the following properties:

  • Interface separation and implementation.
  • Initialization and deinitialization procedures. Both options are optional. The deinitialization procedure is probably missing in an environment with GC (Garbage Collector).
  • The modules used by the program make a dependency graph of the acyclic graph aka (you may have heard about this - cyclic dependencies are not allowed, the dependency is initialized before the dependent module).

Modular programming is essential in building large systems. Each large core is a modular core, whether it is monolithic, hybrid or microkernel.

Sometimes modules can load and unload dynamically. Dynamic modules are an integral part of any expandable system. These can be plugins or, if we are talking about kernels, drivers that are developed and distributed separately from the kernel.

2. Safe and unsafe languages.

Safe languages ​​very strictly determine what can happen in a program. Most importantly, they do not have the concept of a distorted program (or a meaningless program). Each program is valid and its execution always follows the language specification. Regardless of whether the program does what the programmer expects from it or not, it does not matter in this context.

Common features of safe languages:

  • They use garbage collection.
  • They do not have pointer arithmetic. This means that writing or reading to an arbitrary address is not allowed.
  • They prevent access to the array out of range (if there is such a concept). Exceptions or similar mechanisms can be used to signal and recover from such failures.
  • Links (or pointers) have only two possible states: a null link and a link to a valid object. This is guaranteed by the garbage collector. In fact, GC is a key component here. Some languages ​​go even further and do not allow null references at all.
  • Each object (used memory block) has type information assigned to it; an object can be accessed only through a link of the corresponding type, for example. you cannot access an array of integers through a string reference.

You can add more entries to this list, but the basic idea is to ensure that the program can only access valid memory areas using valid operations. Keep in mind that some unsafe languages ​​can convey some or all of these features.

Examples of safe languages: Python, Java, a secure subset of C #.

Insecure languages ​​determine what can and cannot be done in a program, but as a rule, almost nothing is needed to stop the programmer from doing the wrong thing. A program that violates these rules is called an incorrect program. From a language point of view, such a program is meaningless, and the language does not even try to determine its behavior, since it is usually almost impossible to do. In C terms, this behavior is undefined.

Examples of unsafe languages: Assembler, C, C ++, Pascal.

3. The hardware is unsafe and therefore must be programmed using an unsafe language.

Most hardware does not give you a secure environment. There were some processors that used to bind type information to each memory cell (see tagged architecture ), but modern ones do not, because this complicates the process, making it slower, more expensive and less general.

However, there are some features that allow you to implement secure environments in an unsafe hardware environment, such as memory protection, separate address spaces, and separation of execution modes in user mode and kernel mode (for example, supervisor mode).

The core is something that works on bare metal, and therefore most of it must be written in unsafe languages ​​such as C and Assembly. Another reason is a safe environment for maximum productivity.

Microkernel and monolithic core

The monolithic core and its modules work in one common address space. And since everything is usually written in an unsafe language, any part of the kernel can access (and damage) memory belonging to another part of the kernel due to errors in the code. The unsafe nature of this environment makes it impossible to detect or recover from these failures and, most importantly, to predict the behavior of the kernel after such failures.

Microkernel is an attempt to overcome this limitation by moving different parts of the kernel to separate address spaces, effectively isolating them from each other, but providing a safe way to communicate with each other (usually through message passing). This separation creates a safe environment consisting of several unsafe processes, allowing the kernel to recover from the failure of some subsystems.

At the same time, a monolithic kernel can work with particles in a separate address space ( FUSE ), while nothing prevents the microkernel from supporting modules that share the address space with the main part of the kernel.

If most of the kernel runs in the same address space, it is considered a monolithic kernel. If most of them run in separate address spaces, such a kernel is considered a microkernel. If the core is somewhere in between and actively uses both approaches, you have a hybrid core.

Hybrid core

The concept of a hybrid core involves combining the best of the two worlds and was invented by Microsoft to increase sales of Windows NT in the 90s. Joke! But it is almost so. Every important part of Windows NT runs in a shared address space, so this is another example of a monolithic design.

Many people seem to use this term when describing a monolithic kernel that can dynamically load modules. This is due to the fact that in the past monolithic kernels did not support dynamic loading of the module and had to be recompiled every time a module was added to the kernel. Microkernels are not related to the dynamic loading of the module, but to the reliability of the kernel, its ability to recover from subsystem failures.


Answer: Linux is a monolithic kernel.


A monolithic kernel can be modular and can dynamically load modules. Microkernel, on the other hand, must be modular and must be able to dynamically load modules - the whole idea is to run them in a separate address space.


Microkernel is not the only way to overcome the unsafe nature of a monolithic core. Another way is to write a monolithic kernel in a safe language. One of the problems with this approach is that a safe environment must be provided either by hardware (and will be very limited), or it must be implemented in software using unsafe languages. Implementing such an environment will be extremely complex and will most likely have many errors (think of all the errors found in the JVM).

An example of this would be experimental OS Singularity .

+1
source

Well, given that I can go through the quiz tomorrow, I have to help you. Nevertheless, I was still studying, and although my post may have some technical errors, it should be conceptually sound

In principle, as you understand, there are different types of cores for the OS.

Monolithic kernels have all their system functions and services together in one giant program, occupying the same address space. On the other hand, microkernels have minimal system programs and services on a microkernel. Most services that were previously considered part of the kernel (during the monolithic kernel version), such as the process scheduler, etc., are now in user space and are called servers. these servers interact with each other through the microkernel, using interprocess communication, a form of communication that is established by the microkernel. The modular approach is based on this, making these "servers" dynamically loadable. Thus, it is possible to dynamically load a specific “server” (in this type of kernel, called a module) without a kernel requiring itself to be recompiled.

The Linux kernel is a monolithic kernel, but most varieties of Linux, such as Ubuntu, Solaris, use a hybrid kernel, i.e. combination of a monolithic and modular approach to the core. This is quite common, different kernel structures have different pros and cons, and a hybrid structure is required to achieve balance.

0
source

See fooobar.com/questions/36612 / ... for some information about your question. In short, it seems like you're curious ...

... reading a modular concept that states that a new module for a driver can be added without recompiling the kernel, which contradicts my assumption that Linux uses a monolithic kernel. a monolithic kernel works in one address space and as one process ...

These two concepts (“modular core” and “single address space”) do not actually contradict each other. You can create a new kernel module without recompiling the entire Linux kernel. When you load this new kernel module, it will actually be loaded into the same address space as the running kernel. The link above ...

Do not confuse the term modular core as something monolithic. Some monolithic kernels can be compiled as modular (for example, Linux), it is important that the module is inserted into and launched from the same space that processes the main functions (kernel space).

As you have already found, there are several ways to classify kernels, and different types are not necessarily mutually exclusive.

0
source

Source: https://habr.com/ru/post/1272102/


All Articles