The Linux Kernel Is Just A Program

Anyone considering using the Raspberry Pi as an embedded device should take a look at void-linux with runit. It’s particularly well-suited for the ARM architecture. We use it in combination with Zig to develop automated process controllers that are lean and robust.

1 Like

I’ve been using raspberry pi os lite 64bit and the PREEMPT_RT kernel build (from raspberry pi as well since they recently started publishing builds) for the same purpose (industrial controls)

1 Like

Does is work without systemd?

It’s based on Debian so it’s systemd, haven’t investigated anything else

Back in 2012, I wrote a program called bliss-initramfs that allowed someone to install Linux on top of OpenZFS in Gentoo Linux. You can see the last line of my initramfs generator makes a call to a “SwitchToNewRoot” function, which ultimately just made a call to exec switch_root <new root> <init script/program>. This transitions the early system (that’s currently booted inside an initramfs environment) into the actual live system (the one that’s running either runit, systemd, openrc, sysv, etc), which is usually called and located at /sbin/init:

Given modern Linux systems are more complicated than this, the above code should give you a clear and relatively minimal example of this early boot transition into PID 1. Although now I’m on FreeBSD so I no longer need to use my own application since FreeBSD has OpenZFS built into the OS and supports booting from it natively :D.

Below is also a copy/paste of the switch_root(8) from some manual page you can find online (or on your local Linux box):

NAME         

       switch_root - switch to another filesystem as the root of the
       mount tree

SYNOPSIS         top

       switch_root [-hV]

       switch_root newroot init [arg...]

DESCRIPTION         top

       switch_root moves already mounted /proc, /dev, /sys and /run to
       newroot and makes newroot the new root filesystem and starts init
       process.

       WARNING: switch_root removes recursively all files and directories
       on the current root filesystem.

If you check out my USAGE page, you’ll be able to see some examples of how to set this up, which demonstrates the following:

  1. You turn on your machine, stuff happens, bootloader gets called.
  2. Your bootloader entry calls the linux kernel with specific parameters it also includes the parameter for the initramfs (or initrd) image you want loaded on early boot. Back in the day systems were much simpler (didn’t need to be decrypted, didn’t need network boot for a lot of cases, didn’t need customize filesystem modules loaded, etc), thus an initramfs image wasn’t needed. If you need to decrypt your machine, this is considered a complex early boot operation that the Linux kernel doesn’t usually know how to do by itself, thus that’s why you need to boot into a minimal root filesystem (considered early boot) that understands how to do all of this “glue”.
  3. Initramfs image gets unpacked and system gets transitioned into this. The /sbin/init script in this case would be the initramfs entry point. Once all of the magic happens in here (like loading our OpenZFS kernel modules so that Linux understands how to read/write to an OpenZFS drive), it can go ahead and decrypt the drives as well, import the pools, and get everything ready to transition into the final init system that’s installed on the actual rootfs (like OpenRC, systemd, etc)
  4. Initramfs will make a call to switch_root that will pivot the rootfs that was mounted inside the initramfs in a temporary directory to make it the real rootfs and call the final init living inside that real rootfs.
  5. System transitions into the live system.
3 Likes