e-tinkerer

A Place for my train of thought, mainly electronics, mcus and math

Linux init systems

The embedded linux has four main components: a toolchain, a bootloader, the linux kernel and a rootfs. With these components in place we have a bootable system running userland! In this post let’s look into the first process that in run in the userland: the init process. After this we look at one simple yet powerful init system called OpenRC.

The brief history of init process

The kernel is implemented so that it calls the init process after it has completed booting. The linux kernel is loaded into memory and called with command line arguments. The kernel initializes the system, loads in-tree kernel modules, detects and initializes hardware. This is a distilled description of the kernel boot. When th boot process is done The first process the kernel calls is an executable /sbin/init. The /sbin/init should be an executable file. Technically it can be a shell script or an executable binary. If the /sbin/init is s schell script the script must start with a shebang #!/bin/sh for the kernel to know to interpret the file with a shell. If the /sbin/init is a binary file it need to have the int main() function implemented. The called executable then becomes the prodess with PID 1.

Now if a system has a Python interpreter included in PATH technically you could run a .py script as the first process in the system. That might not be much of use but a fun experiment for sure!

Now think about the responsibility of the init. In the system the init should not return nor crash at runtime. This would result in a kernel panic. Modern linux and embedded linux systems have evolved to use more sophisticated inits such as systemd on Ubuntu based systems. A more seasoned systems developer recognizes the sysvinit and the tacky syntax it uses. On Gentoo there is the OpenRC, a kind of middle-ground between systemd and sysvinit, and some other smaller systems like runit (docs on runit) and minit (post about minit on medium.com). Some systems like OpenRC have added modularity. Besides using start-stop-daemon it supports separate daemon monitoring processes such like s6 (more info on OpenRC and s6 here).

But before dwelling into any more of these detailed init system implementations it is noted that the main reason for having a dedicated init system is process management. An init system treats daemons and user processes as services. Often command line calls like start and stop are provided to manage the running services. In it’s bare bones the init systems is just an iterator that reads in a list of instructions, called init scripts, that describe how to configure and start a service. Starting services as a part of a loop already allows a single init script startup to crash. A crashed init script is then cleaned and the init system continues to the next script in the list. Once all init scripts are run the init systems goes to sleep and listens for command calls.

Essetial daemons and systemd

On a linux system running full desktop environment there are a lot of daemons. The system manages internal clock with ntpd, hot-plugged devices with udev, maybe an ssh server with sshd etc. The user needs not to burden themself by manually running these. systemd in itself is a lot more than an init system that starts and stop services.

TBC