How Does Linux Boot?

Every operating system has a boot process. Linux is no different. In this section, we’ll go over the basics of the boot process and explain each component.

There’s a ton of processes happening between powering up a Linux system and when it finally gets to a blank prompt. The boot process can be explained very simply, then we’ll go deeper. 

Here’s the summary:

  • A BIOS or UEFI boot firmware runs a bootloader 
  • The bootloader finds the kernel image from the disk, loads it into memory or RAM and starts it up with kernel parameters
  • The kernel initializes hardware devices and drivers needed to talk to its devices and mounts the root filesystem. 
  • The kernel next starts a process called init and gives it a process ID of 1. On newer systems, this is now replaced by systemd
  • Init brings up the rest of the system processes needed like networking services, web daemons and logging services.
  • Init finally allows you to login near the end of the boot sequence

Linux Boot Process – BIOS and UEFI

In order to understand the Linux boot process further, we should familiarize ourselves with BIOS and UEFI and the differences between the two systems. 

BIOS

BIOS stands for Basic Input/Output System. BIOS is a firmware used in the boot procedure to find the bootloader among some other secondary system functions like changing boot disk order and network settings. BIOS firmware is stored on an EPROM chip, which allows for firmware updates from the manufacturer. 

Once BIOS boots up, its goal is to search for the Master Boot Record (MBR) and execute it. The MBR contains the primary boot-loader in the first 512-bytes of the disk.

UEFI

UEFI or Unified Extensible Firmware Interface is newer and has the same goal of starting the system as BIOS does. However, UEFI stores the initialization data in a .efi file, rather than storing it on the firmware. This .efi file is stored on the disk of the system on a partition called the EFI System Partition, alongside the bootloader. The GUID Partition Table (GPT) format is used in UEFI systems.

UEFI was developed to improve on some of the shortcomings of BIOS, such as:

  • Faster Boot Time 
  • Larger Disk Size support: BIOS supports 2.2 TB, while UEFI supports 9 zettabytes (huge! As of today…)
  • Secure Boot – UEFI can utilize the Secure Boot feature to require that boot loaders are digitally signed, preventing malware from being loaded on the system.

Today, UEFI is the standard and BIOS has become archaic and dated. 

Linux Bootloader

Once BIOS or UEFI has found the bootloader and executed it, the bootloader takes over. The bootloader’s main goal is to start the Linux kernel. It does this by finding the kernel, loading it into memory and passing in any kernel parameters that may be needed. 

During this process, the kernel has still not been loaded, so accessing the disk must be done via slower device drivers than the one the system uses once it’s booted. 

The most common and ubiquitous Bootloader is GNU GRUB or GRand Unified Bootloader. There are also other Linux bootloaders like LILO (Linux Loader), BURG, Syslinux and core boot. These bootloaders were developed to be faster, simpler or have different features than GRUB. 

Init and User Space Start

After the bootloader loads the kernel into memory, it starts its first user-space process, init. This kicks off the rest of the process to bring the system completely up by starting essential services. The init process will always be assigned a process id of 1. Once init starts, its goal is to start up the rest of the programs that are necessary to run the system. 

Systemd is the newest and current standard for init on modern Linux distributions. System V init (SysV) is found on older Red Hat Enterprise Linux distributions. Upstart is the init that was used on older Ubuntu distributions (pre 15.04). There are a few other init systems used for embedded applications, cellphones and other devices. The three I mentioned are the ones you should be most familiar with: Systemd, SysV and Upstart. We’ll be working with and covering systemd. 

sytsemd

systemd works with targets which can be thought of as goals for systemd to reach. Targets are a type of unit used to group other units and define the system state that should be reached. A unit is a file that has instructions for how to start a daemon or system service and the dependencies for starting it. The dependencies for a service are also units. 

For example, consider a Web Server like Nginx. It doesn’t make sense to start up a web server if the system doesn’t already have its network online and functional. A Web Server or Nginx unit file will have a dependency on the network unit file. 

Let’s take a look at how systemd boots the system:

  • Systemd loads configuration files or units, which are typically located in /etc/systemd/system or /usr/lib/systemd/system
  • Based on those configuration files, systemd determines its boot goal or target, this is usually default.target. systemd then figures out dependencies of the boot target and activates those. 
  • units are configuration files used to describe a resource managed by systemd. Units might be services, sockets, devices and more. Systemd units are started in parallel based on the dependencies they define.
  • Services are the most common unit, these define daemons or background processes running on the system. Systemd starts these up as well if they are a dependency of the unit files

An Example Unit File

Let’s take a look at an example systemd unit file for the popular web server, Nginx. This file would typically be located at /lib/systemd/system/nginx.service:

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.targetManaging systemd Services

This config file looks very similar to .INI file formats you might have seen in the past. The sections are denoted by square brackets for Unit, Service and Install. Each of the keys and values underneath the sections are known as directives.

The Unit section contains a description of the service along with an After and Wants directive. The After directive specifies units that should be started before this unit file. The Wants directive is similar to a directive called Requires, but less strict. It tells systemd to attempt to start any units listed here when this unit file is activated. 

Under the Service section there are instructions for how systemd should start the daemon. The nginx binary lives at /usr/sbin/nginx. The ExecStartPre, ExecStart, ExecReload and ExecStop directives tell systemd what program it should run and with what options before the unit starts, when the unit starts, when it reloads and finally when the unit is stopped.  

The last section is Install. It’s an optional section. The WantedBy directive sets up a dependency to specify target units that should be started when the current unit is enabled. 

This is just the beginning of Unit Files. Hopefully, this gives you a real-world example of a Unit file you might find running in production. Next, we’ll look at interacting with systemd unit files via systemctl. 

Systemctl

Systemctl is a command-line tool used to control systemd. We most often use it to start, stop, restart, enable or disable a service. Starting and stopping are pretty clear, but what about restarting and enabling or disabling? 

Restarting a service stops it and starts it again. You might restart a service when it isn’t working properly or when you’ve changed a configuration file that you want to be applied.

Enabling or disabling a service will mark the service to start at boot or to not start at boot. Pretty simple. 

Let’s look at a few commands:

systemctl list-units - List all active units
systemctl status <service> - View the status of a unit
systemctl start <service> - Start the service
systemctl start <service> - Stop the service
systemctl restart <service> - Restart the service
systemctl enable <service> - Enable a service to start on boot 
systemctl disable <service> - Disable a service from starting on boot

Systemd and the systemctl command are essential pieces of the Linux operating system today. Understand them well and you will thrive in your Linux journey!

This has been a sample of Shell Samurai. If you want to master the Linux Command Line, pick up a full copy of the book below!

You can get 20% off with coupon code KERNEL at the link below

Leave a Comment