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
start-stop-daemon
man page