Skip to content
What's a (minimal) Linux?

What's a (minimal) Linux?

Published: at 01:37 PMSuggest Changes

If you read this post, this blog, you certainly know (and use?) Linux. And even if you don’t, it’s probably part of your life. Because Linux won!

These days, it’s everywhere: in the Cloud, its servers, but also phones, tablets, TVs, cars, fridges, watches, cameras, routers, IoT devices, supercomputers, space stations, Mars rovers, nuclear submarines, airplanes, drones, robots, game consoles, smart speakers, smart homes, smart cities, smart grids, smart factories, smart farms, smart hospitals, smart cars, smart everything. Sometimes, in desktop computers too…

Let’s talk about Linux

But when you discuss it with people, even confirmed users, you realize there are still a lot of questions and misconceptions about Linux. What is it, its kernel, why is there people yelling at you when you don’t write GNU/Linux, what makes a distribution different from another, etc.

So, let’s try to clarify things a bit with a blog post series and some practical stuff. It won’t be that technical, but I hope it will help some to better understand Linux and its ecosystem, and why it’s so precious.

Sorry BSD team, I won’t elaborate more on it. Maybe later 😬

Do you GNU?

As stated by Wikipedia, Linux is not just A thing, it is “a family of open-source Unix-like operating systems based on the Linux kernel, an operating system kernel first released on September 17, 1991, by Linus Torvalds”.

I won’t go into the details of the history of Unix and Linux, Wikipedia is far better than me for such things. But you got it: we use this name to talk about the kernel and operating systems (OS) based on it.

In most situations, these OSes, or distributions, includes tools from the GNU project. There are a lot, almost 400!. All with the same Free Software philosophy. It’s why you should then talk about GNU/Linux.

(Compile) the kernel

Kernel is the core of the system, the one talking to the hardware, managing resources, etc. It’s (almost) the first thing that starts during boot.

Linux is open source, so you can read it, modify it, compile it, and use it. By the way, let’s demystify something: no, it’s not that hard to compile and use your own kernel. You don’t believe me? Let’s do it!

First, download a kernel tarball (on a Linux based system), and extract it:

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.8.8.tar.xz
tar xf linux-6.8.8.tar.xz
cd linux-6.8.8/

Configure with default settings and compile it (using all CPU cores):

make defconfig
make -j$(nproc)

Wait some minutes and… it’s done! Install it could be as easy as a make install. But many distributions prefers to package it or provides their own tools. Why? Because the hard part is the configure step. You never use kernel with its default settings: you fine tune it, add some features, remove others, etc. And it’s not that easy to do it right. But try it!

# If you want check and/or modify kernel configuration
# Result is stored in .config file
make clean
make menuconfig
make -j$(nproc)

You almost have a Linux (system)

Once compiled, Linux kernel is available in the arch/x86/boot/bzImage file, but also in the vmlinux file. The first one is to boot the system, the second one is for debugging. Both are ready to use.

You wanna try? Let’s download qemu, one of the fabulous tools made by Fabrice Bellard, and run your kernel in an emulated x86_64 machine:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage

You’ll see it booting. But soon after that, it fails. Why? Because you need more than just the kernel to have a working system. You need a lot of things: a file system, a network stack, a shell, a package manager, tools, themes, wallpapers, etc. That’s what distributions are for.

They provide you all these things, pre-configured, ready to install from an ISO image. They are a lot, for different purposes: servers, desktops, mobile, embedded systems. With different philosophies, preferences, strategies for packages management, etc.

You want to discover them? There are 300+ listed on Distrowatch, find yours!

Init it!

To get a working system from a compiled kernel, we need an initial ram disk (known as initrd or more recently initramfs). It’s a small file system containing an init command, loaded into memory at boot time.

It contains tools to mount the real file system, and then start the OS. There are many ways to create it, from mkinitramfs to dracut. But let’s keep it simple, using the cpio archive software and a “Hello, world!” C program.

First, create a initramfs folder and a simple init.c file:

mkdir -p initramfs

cat > init.c <<EOF
#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}
EOF

Compile it with -static to get a standalone binary in initramfs folder:

gcc -static init.c -o initramfs/init

Then create the initramfs archive with cpio and gzip it:

cd initramfs
find . | cpio -H newc -o | gzip > ../initramfs.cpio.gz
cd ..

Now, boot the kernel with this initramfs file. Here we use qemu with more complete options to enable KVM, native CPU instructions, a serial console to see the output of the init program. We also disable the graphical output, and ask to stop the system after the init program ends/panics:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd initramfs.cpio.gz \
    --enable-kvm -cpu host -nographic -no-reboot \
    -append "console=ttyS0 panic=1"

The kernel starts, the initramfs compressed file is mounted, the init script found and started. Then, the “Hello, world!” message is printed before the system stops (because there is nothing more to do).

It’s a good start, isn’t it? But we want more than that…

Hello, world! from qemu

Embed BusyBox

We want a shell, some apps, etc. For this example we won’t embed the full GNU toolset, but a subset of them: BusyBox. It’s a single binary containing many common Unix commands, like ls, cat, cp, mv, rm, grep, etc.

Download it, configure it with static linking, compile it, and install it in the initramfs directory:

wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1/

# We configure and set CONFIG_STATIC=y to get a standalone binary
make defconfig
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config

# Compile and install it in the initramfs directory
make -j$(nproc)
make install CONFIG_PREFIX=../initramfs

Add some folders to mount a working file system, and an init executable script to start sh shell from BusyBox:

cd ../initramfs/
mkdir -p {dev,proc,sys}

cat > init <<EOF
#!/bin/sh

mount -t devtmpfs none /dev
mount -t proc none /proc
mount -t sysfs none /sys

echo "Welcome to my minimal Linux system!"
uname -a

# Understand this command: https://busybox.net/FAQ.html#job_control
exec setsid cttyhack /bin/sh
EOF

chmod +x init

Then create the initramfs file with cpio and gzip it:

find . | cpio -H newc -o | gzip > ../initramfs.cpio.gz
cd ..

Boot the kernel with this new initramfs file:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd initramfs.cpio.gz \
    --enable-kvm -cpu host -nographic -no-reboot \
    -append "console=ttyS0 panic=1"

You should see the system booting and get a shell prompt:

[    0.990881] Freeing unused kernel image (initmem) memory: 2680K
[    0.991694] Write protecting the kernel read-only data: 26624k
[    0.992787] Freeing unused kernel image (rodata/data gap) memory: 1568K
[    1.041711] x86/mm: Checked W+X mappings: passed, no W+X pages found.
[    1.042542] x86/mm: Checking user space page tables
[    1.090060] x86/mm: Checked W+X mappings: passed, no W+X pages found.
[    1.090875] Run /init as init process
[    1.093103] mount (50) used greatest stack depth: 13864 bytes left
Welcome to my minimal Linux system!
Linux (none) 6.8.8 #1 SMP PREEMPT_DYNAMIC Wed May 1 14:42:21 CEST 2024 x86_64 GNU/Linux
~ #

You can now use some commands:

# Get informations about CPU and memory
# It's UNIX, everything is a file
cat /proc/cpuinfo
cat /proc/meminfo

# List devices and binaries
ls /dev/
ls /bin/
ls /sbin/

# Get system uptime
uptime

It’s your first minimal Linux system, it uses less than 15 MB of storage, less than 10 MB of RAM. Have fun with it! 🎉

PS: You’ll find the full script from this guide here.


Previous Post
Chroot to any Linux (to test it)
Next Post
Why I not use WordPress for this blog