The Linux Kernel

You can use the Linux Kernel as a black box, in other words, using it while not knowing very much about how it works. I don’t know all that much about it and I’ve been using Linux, almost exclusively, for more than 15 years now.

I just want to be able to install, operate, maintain and repair my own Linux operating systems. Here are some of the notes I’ve been taking, as I study and learn how Linux works.

They are probably not very thorough. I’m still figuring out what’s important to know, what questions should I be seeking answers for. This story will be updated, whenever I learn new things about the Linux kernel.

Its just a start. This is an unfinished story. Pay attention to the patterns.

The Kernel

An operating system (OS) is software that controls the hardware of a computer. It consists of

  • A bootloader is software that controls the process of starting your device. The bootloader checks your hardware and starts your kernel.
  • The kernel is the core of the system. It manages the CPU, memory and peripheral devices.
  • Daemons are background services, like drivers, which allow the kernel to communicate with and control your hardware.
  • D-Bus (Desktop Bus) is your InterProcess Communications system (IPC), which enables your applications to communicate with the kernel and vice versa.
  • The system daemon of D-Bus is launched at start up and is primarily used for managing hardware.
  • The session daemon of D-Bus is launched when you log into your desktop and primarily manages your desktop and applications.
  • The shell is a program, through which you operate your computer using text commands in a command line interface. Zsh is my favorite shell.
  • Your Graphical Server is the sub-systems that display the graphics on your screen. Kwin and Wayland are the more advanced replacement for the X Windows System.
  • A Desktop Environment, KDE is a very Kool Desktop Environment.
  • Tiling window managers are a popular alternative to a full desktop environment.
  • Applications are programs that perform a user’s tasks, such as Konsole, Kontact, LibreOffice and Firefox.

The kernel is in a high priority system state, which includes protected memory space and full access to your device’s hardware. That system state and memory space are known as kernel space.

Device drivers connect the Kernel to the hardware of your system. Knowing how to install and configure device drivers can be very useful for connecting your computer to other devices, like printers and monitors.

Once you understand how Linux works, learning how to port Linux to hardware, such as a smartphone, might be an interesting subject to learn.

The System Call Interface, Linux uses D-Bus, connects your kernel to user space, where all your applications operate. D-Bus is an InterProcess Communications (IPC) “manager.” It manages the ports and sockets automatically, so you don’t have to do it manually.

Good info about D-Bus

The system call interface is a communication system, which your applications use to communicate with each other and with the kernel, to ask the kernel to do things that make the applications function.

The communications between the kernel and the device drivers, and the kernel and the system call interface, are two way communications. The kernel uses device drivers to control devices. It uses the system call interface to control the applications running on your desktop. The applications and the devices, “call” the kernel to ask for kernel resources.

Devices are usually machines, such as your laptop, including the mouse and keyboard and the CPU and memory in your computer, your printer, a USB that you plug into your computer and any other hardware you want to control. Applications are the programs you run on the computer.

Your kernel turns systemd on. systemd turns on and controls your user space. Your applications run in user space, where they can access a subset of your computer’s resources, via kernel system calls. User level applications, such as Konsole, Kontact, LibreOffice and Firefox are created using the core services provided by the kernel.

The kernel was first released on September 17th, 1991, by Linus Torvald at Helsinki University. It eventually adopted the GNU/GPL v2 (GNU is Not Unix/General Public License).

With many academic and corporate supercomputers running Linux and the Linux kernel based Android operating system, working on millions of smart phones all over the world, Linux is the most common general purpose operating system in the world. Both Android and OS X are forks of Unix, just like Linux is.

The Linux kernel is a monolithic computer operating system, rather than a micro-kernel or a hybrid. OS X and Windows are hybrids. There are many different distributions of Linux based on the Linux kernel. The monolithic kernel encompasses the Central Processing Unit, the memory and the IPC. It also handles device drivers, system server calls and file system management.

The monolithic design is faster, but less secure than micro-kernels, which keep user services separate from the kernel. Ubuntu has started containerizing applications in Snap Packages, accomplishing the security advantages of a micro-kernel. Pop-OS! uses Flatpak.

The Linux kernel is written with the C and Assembly programming languages. There is also a lot of Python2.7 in Linux. One time, while upgrading Python, I removed Python 2.7 from a Linux installation. That was the end of that operating system. I suppose the Python could be in the drivers and/or the user space.

  • Operating System Operations
    • Process Management
    • Memory Management
    • File Management
    • Device Management

Hardware

The Linux kernel also manages the system’s hardware using interrupts, just like systemd uses interrupts to call for kernel resources to run applications.

When the hardware wants to interface with the system, an interrupt signal is issued that interrupts the kernel running in the processor. In order to synchronize various processes, the kernel can disable a single interrupt or all of them.

Interrupt handlers do not run in a process, they run in an interrupt context, not associated with any process. This enables interrupt handlers to quickly respond to an interrupt and then finally exit.

Linux supports dynamic loading of kernel modules. systemd merges all the modules into one central system configuration and service management platform.

The kernel is preemptive. It has symmetrical multiprocessor support. Linux provides an object-oriented device model, with device classes, hot-pluggable events and a user-space device file system.

System calls and Interrupts

Applications pass information to the kernel through system calls. Libraries contain functions that applications work with. They use the system call interface to command the kernel to execute a process the application needs.

Interrupts are the signals Linux uses to manage system hardware. The kernel interrupts the processors to command them to do things. The processor, in turn, interrupts the kernel to command it to do things. This is how the operating system communicates with the hardware.

An IRQ is an Interrupt ReQuest. IRQs are signals, asking a CPU to do some task. An IRQ line is a channel of communications between the kernel and a CPU. Exceptions are a particular kind of IRQ, involving some kind of error.

IDT is the Interrupt Descriptor Table. APIC is the Advanced Programmable Interrupt Controller. LAPIC is a Local APIC. The interrupt handler’s first task is reserving registers in the CPU.

When a CPU receives an interrupt, the interrupt handler uses assembly language code to reserve registers for the operation in the CPU and C functions to execute the commands. An IRQ n is stored in the interrupt[n] entry and then copied into the interrupt gate included in the proper IDT entry.

Each CPU in a computer has a hard IRQ stack and a soft IRQ stack. Hard IRQs have a higher priority than soft IRQs. The hard IRQ stack and the soft IRQ stack are each, one page frame lists of requests that can be sent. Hard IRQ stacks are contained in a hardirq_stack array. Soft IRQ stacks are contained in a softirq_stack array.

Interrupt Service Routines handle interrupts by executing an operation specific to one type of device. Interprocessor Interrupts are handled as direct messages on the bus (the computer’s communications system) that connects the Local APIC of all the processors.

Two distinct Application Programming Interfaces (API) exist, kernel-userspace and Kernel internal. The kernel-userspace API is the Linux API. It consists of the System Call Interface and the subroutines from the GNU C Library. It gives user space programs access to system resources and kernel services.

The Linux Application Binary Interface (ABI) is a kernel-user space interface, which exists between modules. ABIs access external code that has already been compiled, while APIs are structures for managing software. Linux distributions, rather than the Linux kernel, define important ABIs.

An ABI is the source code an application is made of. And API is the code an application uses to interact with the operating system.

ACPI is the Advanced Configuration and Power Interface specification. It is an open industry standard that transfers control of power management from the BIOS to the operating system.

Source: Interrupt Handling

The C Standard Library

All system calls are included in the GNU C library. The Linux API includes the system call interface and the GNU C library, named glibc in Linux.

Qt and GTK are libraries that KDE and GNOME use to build their applications. The libraries are objects and functions that programs can call on to do things, without having to create those objects and functions from scratch.

Your computer’s processors, my computer has eight processors on one chip, each one operating at 2 or 3 gigahertz, is performing billions of these calls and calculations every second.

POSIX

The Portable Operating System Interface (POSIX) is the standard for maintaining compatibility among operating systems. It declares the API, together with utility interfaces and command line shells. The Linux API includes the usable features defined by POSIX and additional features, including:

  • Cgroup subsystem
  • The Direct Rendering Manager’s system calls
  • A readahead feature
  • getrandom call
  • System calls such as futex, epoll, splice, dnotify, fanotify and inotify

The Linux Loadable Kernel Module (LKM)

You can add code to your Linux kernel by adding source files to the kernel source tree. You can also add code as a loadable kernel module, while the kernel is running. There are three kinds of LKMs: device drivers, file system drivers and system calls.

The advantage of installing LKMs, instead of binding into the base kernel are

  • You don’t have to rebuild your kernel, saving time and avoiding errors.
  • LKMs assist you to investigate system problems, such as bugs.
  • LKMs save space, because you only load them when you use them.
  • Faster maintenance and debugging.

You can use LKMs as

  • Device drivers are how the kernel exchanges information with hardware. A kernel must have a device’s driver before using it.
  • Filesystem drivers translate the contents of a filesystem
  • System calls enable programs in user space to acquire services from the kernel.
  • Network drivers interpret network protocol.
  • Executable interpreters load and manage executables.

Compiling the Linux Kernel

Compiling the Linux kernel is actually fairly simple. Download the source code from https://kernel.org. Read the manual. Follow directions. …

Architecture

A kernel is simply a resource manager. The resources being managed may be processes, memory or hardware devices. It manages and arbitrates access to resources between multiple competing users.

A GNU C Library provides a forum for the system call interface to connect to kernel space, allowing communication back and forth between the kernel and user space. It’s a library of prerecorded sentences and paragraphs of code that the kernel, hardware and applications can use to communicate with each other.

The kernel is organized into three primary levels. The system call interface is the topmost level and executes basic actions like read and write. The kernel code is located inside the system call interface. It is common to all processor architectures supported by Linux and is sometimes defined as architecture-independent kernel code.

Architecture-dependent code is inside, or below, the architecture-independent code. It forms a Board Support Package (BSP). This includes UEFI/GRUB, which places the Operating System and device drivers into memory and starts them.

The architectural perspective of the Linux kernel consists of:

  • The system call interface is a thin layer used to connect function calls from user space into the kernel. The system call interface may be architecture dependent
  • Process management executes the processes. These are referred to as the thread in a kernel and represent an individual virtualization of a particular processor
  • Linux includes methods for managing the available memory, as well as for interfacing with the hardware mechanisms for physical and virtual mappings. For efficiency, memory is managed as pages. Swap space is also provided.
  • The virtual file system provides a standard interface for the file system. It provides a switching layer between the system call interface and the file systems supported by the kernel.
  • The network stack is designed as a layered architecture, modeled after certain protocols.
  • Device drivers, which make hardware devices usable, are a significant part of the source code in the Linux kernel. They enable the kernel to communicate with and manage devices.
  • Architecture-dependent code, UEFI/GRUB, the elements that depend on the architecture of the hardware on which they run, must consider the architectural design for normal operations and efficiency.

Cgroups

Control groups, usually referred to as cgroups, are features of the Linux kernel which allow processes to be organized into hierarchical groups, whose usage of various resources can be monitored, prioritized and limited.

A cgroup is a collection of processes, which are bound to a set of limits or parameters defined via the cgroup filesystem.

The kernel’s cgroup interface is provided through a pseudo-filesystem called cgroupfs. Grouping is implemented in the core cgroup kernel code. Resource tracking and limits are implemented in a set of per-resource-type subsystems (memory, CPU, and so on).

A subsystem is a kernel component that modifies the behavior of the processes in a cgroup. Various subsystems have been implemented, making it possible to do things such as limiting the amount of CPU time and memory available to a cgroup, accounting for the CPU time used by a cgroup, and stopping and starting execution of the processes in a cgroup. Subsystems are sometimes called resource controllers, or simply, controllers.

The cgroups for a controller are arranged in a hierarchy. This hierarchy is defined by creating, removing, and renaming subdirectories within the cgroup filesystem. At each level of the hierarchy, attributes (e.g., limits) can be defined. The limits, control and accounting provided by cgroups generally have effect throughout the subhierarchy underneath the cgroup where the attributes are defined. So, the limits placed on a cgroup at a higher level in the hierarchy, cannot be exceeded by descendant cgroups.

Nodes

The no-processes-in-inner-nodes rule means that it is not permitted to have processes directly attached to a cgroup, which also has child cgroups and vice versa. In other words, a cgroup is either an inner node or a leaf node of the tree, and if it’s an inner node, it may not contain processes directly; and if it’s a leaf node, then it may not have child cgroups.

(There are some minor exceptions to this rule. For example, the root cgroup, which maintains kernel threads, is special and allows both processes and children)

The single-writer rule means that each cgroup has only a single writer, i.e. a single process managing it. It’s OK if different cgroups have different processes managing them. However, a single process should own a particular cgroup, and that ownership is exclusive, and nothing else should manipulate it at the same time. This rule ensures that various pieces of software are not constantly stepping on each other’s toes.

Tree Setups

Unified — this is the simplest mode, and exposes a pure cgroup v2 logic. In this mode /sys/fs/cgroup is the only mounted cgroup API file system and all available controllers are exclusively exposed through it.

Legacy — this is the traditional cgroup v1 mode. In this mode the various controllers each get their own cgroup file system mounted to /sys/fs/cgroup/. On top of that, systemd manages its own cgroup hierarchy for management purposes as /sys/fs/cgroup/systemd/.

Hybrid — this is a hybrid between the unified and legacy mode. It’s set up mostly like legacy, except that there’s also an additional hierarchy /sys/fs/cgroup/unified/ that contains the cgroup v2 hierarchy. This mode is a stopgap solution.

Conclusion

The Linux kernel serves as a resource manager for your hardware and your applications. Your applications use the system call interface to communicate with the kernel. The kernel uses interrupts to communicate with the hardware.

Linux is a multi-user, multi-tasking system, allowing many people to use it at the same time and allowing many projects to run at the same time.

The modular nature of the Linux kernel enables you to add significant modifications without rebooting the system.

The monolithic structure of the kernel makes it faster. The main weakness is that if any of its services fail, the whole system fails. Newer versions of Linux have addressed this problem by adding new services as modules. Snap packages and Flatpak install applications within containers to protect the kernel from the packages and to protect the packages from each other.

Sources