How Does Linux Boot? Part 5: The Kernel Starts The First Process

So far in our detailed tour of the Linux boot sequence (which started here) we have seen how the UEFI firmware on modern hardware can call a “shim” program to support Secure Boot, which in turn runs the GRUB boot loader to find, load, and start the kernel. The kernel has loaded device drivers for appropriate SATA and/or SCSI controllers from an initial RAM disk image, and with those it has found the disk partition containing the root file system. Of course it has also detected the CPU, memory, PCI bus(es), and other fundamental hardware on the motherboard.

The kernel does all the kernel-space work: interacting directly with hardware, managing running processes by allocating memory and CPU time, and enforcing access control through ownership and permissions.

Now the kernel is ready to start the first user-space process, PID 1, the ancestor of all processes to come later. This process keeps running as long as the system is up, and it is responsible for first getting the system into its target run state, and then handling any later state changes including the eventual clean shutdown for poweroff or reboot.

The kernel expects to find the program /sbin/init to handle this crucial task, although the kernel will look in a few more places if it isn’t there. Here is the relevant block of code from /usr/src/linux/init/main.c in the kernel source code:

static int run_init_process(const char *init_filename)
        argv_init[0] = init_filename;
        return do_execve(init_filename,
                (const char __user *const __user *)argv_init,
                (const char __user *const __user *)envp_init);

[ ... ]

if (!run_init_process("/sbin/init") ||
    !run_init_process("/etc/init") ||
    !run_init_process("/bin/init") ||
        return 0;

panic("No init found.  Try passing init= option to kernel. "
      "See Linux Documentation/init.txt for guidance.");

The init program runs a number of scripts sometimes called boot scripts as they handle the user-space part of starting the operating system environment, and sometimes called init scripts because they’re run by init.

So far this is all very familiar to administrators of any Unix-family operating system, the open-source ones like Linux and the BSD variants, and the commercial ones like Solaris, HP-UX, AIX, and others. Learning Tree’s Linux server administration course strives to be about Unix-class operating systems in general as much as is practical. But here’s where things get weird:

Most of the very latest Linux distributions do not have an init program.

They use systemd instead. It combines many good ideas from Apple’s launchd, introduced with Mac OS X 10.4 and now also incorporated in iOS, with quite a bit of original thinking. The file /sbin/init is a symbolic link pointing to /lib/systemd/systemd.

$ ls -l /usr/sbin/init /usr/bin/systemd /lib/systemd/systemd
-rwxr-xr-x 1 root root 929520 Sep 22 /lib/systemd/systemd*
lrwxrwxrwx 1 root root     22 Oct  6 /usr/bin/systemd -> ../lib/systemd/systemd*
lrwxrwxrwx 1 root root     22 Oct  6 /usr/sbin/init -> ../lib/systemd/systemd*

Let’s look at the systemd design philosophy.

Start only what’s needed, start some daemons on demand

The standard example is the CUPS print service. It doesn’t make sense to start the print service a little past mid-way through the boot sequence, while many other more immediately critical services are trying to start. Start it on demand, when someone wants to print something.

For what you do start, aggressively parallelize it

The traditional SVR4 boot sequence involves a long linear sequence of shell scripts, one calling the next which calls the next and so on. I wouldn’t want to try to diagram the complete serial chain of boot scripts.

Each of these must be read individually. The CPU is the fastest component in the system and the disks are the slowest. For each of these scripts the CPU must wait for a large number of potentially useful CPU cycles waiting for disk I/O to complete. And these days, saying “the CPU” is a little old-fashioned on server platforms with many CPU cores.

Systemd creates sockets and passes those sockets to daemon processes as they are started. This is accelerated by first creating all the needed sockets, and then creating all the daemon processes as background processes as quickly as possible, handing the sockets to the processes. The processes communicate among themselves through those sockets as they come up, coordinating all needed order dependencies.

Recode boot scripts in C, use binary executables as much as possible

Shell scripts are very good for rapid development, but they run much more slowly than binaries. The script itself must be created with all the environment overhead, and then every program called from the script must be created as a new process. This is made even worse with the typical nesting of a boot script calling its helper script which in turn calls a number of configuration scripts.

The result

There is no init (although there is a PID 1) and there are no boot scripts. The system boots up and shuts down very quickly.

Service control is completely different in this new environment. Check back next week for the details!

Type to search

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.