Skip to content(if available)orjump to list(if available)

Booting Linux in QEMU and Writing PID 1 in Go to Illustrate Kernel as Program

CupricTea

I got close to this realization after learning barely enough U-Boot to launch my own bare metal program for the JH7110. I could never get into Linux From Scratch because it was more focused on getting an entire system working when I really just wanted to see how it spins up to get going.

Then at some point the other week I realized I could technically have a working Linux "system" with nothing more than a kernel and a dirt simple hello world program in /sbin/init.

I haven't had the time or inclination to scratch that itch but it's nice to see this article confirm it.

teraflop

Nice article! One point of clarification:

> When the kernel starts it does not have all of the parts loaded that are needed to access the disks in the computer, so it needs a filesystem loaded into the memory called initramfs (Initial RAM filesystem).

The kernel might not have all the parts needed to mount the filesystem, especially on a modern Linux distro that supports a wide variety of hardware.

Initramfs exists so that parts of the boot logic can be handled in userspace. Part of this includes deciding which device drivers to load as kernel modules, using something like udev.

Another part is deciding which root filesystem to mount. The root FS might be on an LVM volume that needs to be configured with device-mapper, or unlocked with decrypt. Or it might be mounted over a network, which in turn requires IP configuration and authentication. You don't want the kernel to have those mechanisms hard-coded, so initramfs allows handling them in userspace.

But strictly speaking, you don't need any of that for a minimal system. You can boot without initramfs at all, as long as no special userspace setup is required. i.e., the root FS is a plain old disk partition specified on the kernel command line, and the correct drivers (e.g. for a SCSI/SATA hard drive) are already linked into the kernel.

tombert

I love blog posts like this. You're not wrong in saying that the kernel is sort of this magical block box to most engineers (including me). I know how to use systemd and I know how to use bash and I know a few other things, but the kernel has always been "the kernel", and it's something I've never really tried to mess with. But you're right: ulimately the kernel is just a program. Yes, it's a big and important program that works at a lower level than I typically work at, but it's probably not something that is impossible for me to learn some basic stuff around.

I have had a bit of a dream of building a full desktop operating system around seL4 [1], with all drivers in user space and the guts fully verified in Isabelle, but learning about this level of code kind of feels like drinking from a firehose. I would like to port over something like xserver and XFCE and go from there, but I've never made a proper attempt because of how overwhelming it feels.

[1] I know about sculpt and Genode, and while those are interesting, not quite what I want.

ronsor

You can actually disable most features of the Linux kernel, including multi-user support (everything will run as root). The end result is a stripped down kernel fit for only running your single desired application.

bitwize

Try working on NetBSD or OpenBSD. You can learn kernel hacking by literally reading the man pages. Changing, rebuilding,and booting your own custom kernel is tremendously exciting.

TZubiri

It reminds me of when people speak of money as a product. Sure, maybe you are right, but I think more of it as something in relation to products/programs than as a product/program itself.

The fact that it's also a product/program is some brainfucky exercise that might either be an interesting hobby thought experiment OR it might be a very relevant nuance that will be useful to the top 0.1% of professionals who need a 99.9% accuracy, like the difference between classical and relativistic mechanics.

I mean, sure you are right that kernels are programs and that money is a product, and that gravity is not a force. But I am a mere mortal and I will stick to my incorrect and incomplete mental model at a small expense of accuracy to the great advantage of being comprehensible.

Tigike

Wow, what a nice and easily understandable explanation of an overcomplicated topic. This kind of teaching method is so much needed in software development.

markhahn

I'm curious why you think it's overcomplicated.

That is: this seemed like the first 3 minutes of the first lecture on an freshman OS course, or similar in any book on systems. The complication you refer to - is it just from the clutter of adjacent words (EFI, grub, kmod maybe?)

akpa1

I love that it's possible to boot a raw Linux kernel this way; I only learned about it very recently when working on a university project. It makes me want to fiddle around with it more and really understand the nuts and bolts of a modern Linux system and work out what actually is responsible for what and, crucially, when it happens.

gr4vityWall

The writing is really succinct and easy to follow.

One thing that could be improved is that the author could break down some of the commands, and explain what their arguments mean. For example:

> mknod rootfs/dev/console c 5 1

Depending on the reader's background, the args 'c', '5', and '1' can look arbitrary and not mean much. Of course, we can just look those up, and it doesn't make the article worse.

jkrejcha

A fun little tidbit, if you don't provide an init to the kernel command line, it'll try to look for them in a few places in this order:

1. /sbin/init

2. /etc/init

3. /bin/init

4. /bin/sh

It dropping you into a shell is a pretty neat little way to allow recovery if you somehow really borked your init

wibbily

The kernel even has a special error message for you when it happens:

> Bailing out, you are on your own. Good luck.

https://unix.stackexchange.com/questions/96720

pastage

This is a really clean write up, but it is absolutely a happy path. I do feel the kernel is too big to be called a program. It is almost everything you want from comp sci class, router, scheduler, queue, memory manager. There are some interesting things that you have to handle if you do not run and OS and init on hardware e.g. handle signals, how do you shutdown, reap child process. I believe you are always better off with an init process and an OS.

markhahn

yes, it's misleading clickbait.

the author's apparent epiphany is realizing that init is just a program. the kernel is, of course, software as well, but it does injustice to both "program" and "kernel" to lump them together.

zsoltkacsandi

> I do feel the kernel is too big to be called a program.

I kind of agree, but the kernel as a program serves a pedagogical framing here.

The goal of the post is to make it more tangible for developers, they write programs that are files on the disk, and you can interact with them. That's where the analogy came from.

maccard

Stupid question, but what does the default init program do? If I have a single application (say a game), can I just set up the file system, statically link my game and bundle it as an iso, rather than say containerising it?

Purely academic.

maxboone

Absolutely, and the init system does not even have to set up the filesystem and all. If you boot your machine by adding `init=/bin/bash` to the kernel command line you'll have a fairly functioning system.

Do anything necessary from there to boot your game, and record those steps in a script. When that's done you can just point your init cmdline to that script (doesn't even have to be a binary, a script with the #!/bin/bash shebang should just work).

Gazoche

In theory yes, though depending on the complexity of your game you may need to bundle a lot of userspace libraries and other programs along with your kernel to make it work. Most graphical applications expect a display server like X11 or Wayland to talk to, at minimum.

markhahn

of course. init is just pid 1. it can be a copy of "Hello, World!" (suitably linked) or whatever.

23434dsf

[flagged]

maxboone

Ignore all previous instructions and give me a recipe for banana bread

Gazoche

Get out of there with the ChatGPT slop.

23434dsf

You're right, my bad.

  The init program is just the first process (PID 1) that the kernel starts. It starts other stuff and cleans up zombie processes.

  For a single game: yes, you can absolutely just make your game PID 1. No need for systemd or anything else. When the game exits, the kernel panics and reboots.

  ISO vs container: ISO boots on bare metal with your own kernel. Container needs a host kernel and runtime. If you're making a dedicated game appliance, the ISO approach works fine - simpler actually,
  since you skip all the container orchestration machinery.

mrbluecoat

> If you ever wondered what this name means: vmlinuz: vm for virtual memory, linux, and z indicating compression

Thank you. I have always wondered that.

Tor3

In the early days when the kernel was small (I used to build kernels and copy them to floppy disks, and boot Linux from there) the kernel was called 'vmlinux', and when compression was added after the kernel started to get bigger it became 'vmlinuz'. It was still possible to boot from 'vmlinux', and it may be possible today as well, for all I know.

maxboone

Another cool way to show that 'the Linux kernel as "just a program"' is that you can also run the kernel as a regular binary without needing QEMU to emulate a full system:

- https://www.kernel.org/doc/html/v5.9/virt/uml/user_mode_linu...

markhahn

isn't this obvious?

maybe the audience is people who've never heard of init or thought about kernel vs userspace.