How does Linux start?

Time:2019-9-11

Reference material:

An introduction to the Linux boot and startup processes

This essay can be understood as the integration of translation, personal understanding and notes of this English article.

Expanding reading:

GNU GRUB – Wikipedia

systemd – Wikipedia

BIOS interrupt call – Wikipedia

Multiboot specification – Wikipedia

Chain loading – Wikipedia

Master boot record – Wikipedia

Best Couple of 2016: Display manager and window manager

Brief Analysis of Linux Initialization init System, Part 1: SysV init

Brief Analysis of Linux Initialization init System, Part 2: Upstart

Brief analysis of Linux init initialization system, Part 3: Systemd

 

Preface

Understanding how Linux is started is critical to configuring and troubleshooting Linux startup failures.

This article basically divides the Linux boot process into two parts: boot and startup.

Boot: Start the system D program from the computer boot to the kernel initialization.

Start: From the start of the system D program to the complete start of the system.

The boot loader stage mainly involves boot loader. For the system of CentOS series I studied, the boot loader GRUB is the main one.

  • The 0.x series is an older version, also known as GRUB 1/Legacy, which was mainly used in previous Linux distributions, such as CentOS 5/6.
  • The 2.x series is a new version, also known as GRUB 2, which is now used on mainstream devices such as CentOS 7. Although the new version of GRUB, version number difference is not very big, but GRUB 2 is almost completely rewritten GRUB!

The start-up phase mainly involves the way the system initializes the process (init process/system).

  • CentOS 5: System V init, can be referred to as System V or SysV.
  • CentOS 6:Upstart。
  • CentOS 7:Systemd。

The configuration files are written differently in these three ways of process initialization.

In this essay, the boot and boot versions involved are the current mainstream versions, namely GRUB 2 and System D. GRUB means GRUB 2 if it is not specified below or GRUB appears alone.

The process of booting and starting will be more carefully divided, as shown below.

  1. Boot
    1. BIOS POST
    2. Boot loader(GRUB 2)
      1. Stage 1
      2. Stage 1.5
      3. Stage 2
    3. Kernel initialization
  2. Startup
    1. Systemd

 

Boot process

There are two main ways to start the boot process. One is that the computer is shut down and the user is physically booted; the other is that the computer is on and the user restarts programmatically through GUI or CLI (of course, if there is a physical restart button, it can also be physically restarted).

Translator’s Note: I don’t know why the author said this simple sentence.

BIOS POST

The first step in booting is independent of the Linux system, and all OSs will have this step. This step is the POST (Power On Self Test) function provided by BIOS, which is mainly used to detect whether the hardware can work properly.

If the POST detection fails, the boot terminates, the subsequent steps are no longer available, and the system startup fails.

After POST detection is successful to ensure that the hardware works properly, BIOS releases BIOS interrupt INT 13H, which is used to locate boot sectors on all connected bootable devices. The first boot sector found that contains a boot record is loaded into memory and passes control to the code loaded from the boot sector.

The boot sector is the first stage of the boot loader. Most modern Linux distributions use three bootloaders: LILO, GRUB 1 and GRUB 2. GRUB 2 is the latest and most commonly used bootloader at the current stage.

GRUB 2

The full name of GRUB 2 is “GR and Unified Bootloader, version 2”, which enables computers to find OS kernel files and load them into memory.

GRUB is designed to be compatible with the multiboot specification (see Extended Reading), which allows it to boot many Linux and free OS; it can also chain load (see Extended Reading) proprietary OS boot records.

GRUB also allows users to select different kernels from a Linux distribution to boot. This allows you to boot the previous version of the kernel to work properly when an error occurs in a kernel update or when the update causes an exception to some important software usage.

The configuration file of GRUB 1 is / boot / grub / grub. conf, and that of GRUB 2 is / boot / Grub2 / grub. cfg. Red Hat Linux upgraded GRUB to GRUB 2 from Fedora 15 and entOS/RHEL 7. GRUB 2 and GRUB 1 are functionally the same, but after almost complete rewriting, they are better than GRUB 1.

GRUB 1 and 2 have three stages, which will be outlined in this paper. However, how GRUB is configured is beyond the scope of this article.

GRUB 2 is not officially used in the three stages, namely stage 1/1.5/2, which should be used by GRUB 1, but it is also possible to use these three stages to elaborate GRUB 2.

Translator’s Note: In extended reading, GRUB 2 should be in four stages.

Stage 1

When the self-check phase of BIOS POST passes, BIOS searches for available boot records from connected devices, which are generally located on the MBR of disk. The boot record for stage 1 is called boot. img.

The MBR is located in the first sector of the disk, sector 0, 512B in size. After deducting 64B partition information and 2 bytes boot signature, there is only 446B of space left. This space is very small, so boot. img’s code must be very small. It will not contain the driver of the file system (that is, no code related to the identification of the file system). The only function of boot. img is to find and load stage 1.5. To accomplish the task of stage 1, stage 1.5 must be located between stage 1 itself and the first partition. As shown in the figure.

By Shmuel Csaba Otto Traian, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=28427221

After stage 1.5 is loaded into memory, stage 1 transfers control to stage 1.5.

Translator’s Note: On my CentOS 7 system, the file is located at / boot / Grub2 / i386-pc / boot. img, 512B in size, which should theoretically be less than 446B.

Stage 1.5

As mentioned above, stage 1.5 is located between stage 1 and the first partition, sector 1-62, with a total capacity of 512*62 = 31,744.

Translator’s Note: The capacity of stage 1.5 above is 32,256B, which is 512B more than 31,744. I don’t know why.

The file at this stage is core. img. The author’s file size is 25,389B and mine is 26,664 (/ boot/grub2/i386-pc/core.img). It can be seen that there is still a lot of residual capacity in this stage.

This stage mainly includes a variety of file system drivers, such as EXT family, XFS, NTFS and so on. Only with a file system driver can a file be found/loaded based on its path and name (e.g. / boot/vmlinuz-3.10.0-862.el7.x86_64).

The remaining capacity should allow developers to expand and increase the file system drivers they want to load.

The file system driver loaded in this stage is used to identify the file system where the stage 2 file is located.

The core. img in stage 1.5 of GRUB 2 is more complex and powerful than that in GRUB 1, so stage 2 in GRUB 2 can be located on standard EXT filesystems, but not on LVM partitions.

The location of the standard stage 2 file is on the / boot file system, to be exact, / boot / grub2.

Stage 2

The files at this stage are located in the / boot / Grub2 directory. Not counting the first two stages, there are image files (boot. img and core. img), which are mainly composed of many kernel module files loaded on demand at runtime (located in the / boot / Grub2 / i386-pc directory).

The main function of this stage is to locate and load the kernel file, and then transfer control to the kernel. Kernel files begin with vmlinuz and can be found in the / boot directory for the currently installed system.

[[email protected] ~]# ls -l /boot/vmlinuz-*
-rwxr-xr-x. 1 root root 6224704 Sep 27  2018 /boot/vmlinuz-0-rescue-341d78e441db4d8b985b51fc31f40be9
-rwxr-xr-x. 1 root root 6224704 Apr 21  2018 /boot/vmlinuz-3.10.0-862.el7.x86_64
[[email protected] ~]# file /boot/vmlinuz-*
/boot/vmlinuz-0-rescue-341d78e441db4d8b985b51fc31f40be9: Linux kernel x86 boot executable bzImage, version 3.10.0-862.el7.x86_64 ([email protected]) #1 SMP , RO-rootFS, swap_dev 0x5, Normal VGA
/boot/vmlinuz-3.10.0-862.el7.x86_64:                     Linux kernel x86 boot executable bzImage, version 3.10.0-862.el7.x86_64 ([email protected]) #1 SMP , RO-rootFS, swap_dev 0x5, Normal VGA

GRUB has a pre-boot menu that allows users to select the kernel they want to boot, including rescue mode and recovery mode if properly configured.

Kernel

Kernels are self-expandable compressed files that map to RAM disk mirrors and devices on hard disks in the / boot directory.

/boot/initramfs-0-rescue-341d78e441db4d8b985b51fc31f40be9.img
/boot/initramfs-3.10.0-862.el7.x86_64.img
/boot/System.map-3.10.0-862.el7.x86_64

When the kernel is loaded into memory and executed, it will start the system D process after self-expansion. At this point, the boot process is over and the start-up process is formally entered.

Note: At the end of the boot process, Linux is still unable to perform any production tasks. Because production tasks need specific processes to complete, and the system D process is only the top parent of all production task processes (the first process of the system).

 

Startup

Systemd

System D is the first process in Linux system, the top-level parent process. Its task is to start other processes in the system so that Linux can enter the production environment. Includes mounting file systems, starting and managing services. Systemd tasks unrelated to the startup sequence are beyond the scope of this article.

First, system D mounts the file system according to / etc / fstab, including swap files and partitions. At this point, system D can access the configuration file located in the / etc directory, including its own configuration file. It uses its own configuration file (/etc/systemd/system/default.target) to decide which state or target to boot the system for. Default. target is just a character link file to the real target file. For desktop workstations, it is linked to graphical. target (equivalent to runlevel 5 in System V init). For servers, it is usually linked to multi-user. target (equivalent to runlevel 3 in System V init). Emergency. target is equivalent to single-user mode.

Note: Target and service are units of system D.

Table 1 is a comparison table of the target and the run-level of System V init for system D. System D provides target alias for backward compatibility. Target aliases allow scripts and administrators to switch runlevels using SysV commands, such as init 3, which are, of course, passed to system D for parsing and execution.

Table 1: Comparison of SystemV runlevels with systemd targets and some target aliases.

SystemV Runlevel

systemd target

systemd target aliases

Description

  halt.target  

Halts the system without powering it down.

0 poweroff.target runlevel0.target

Halts the system and turns the power off.

S emergency.target  

Single user mode. No services are running; filesystems are not mounted. This is the most basic level of operation with only an emergency shell running on the main console for the user to interact with the system.

1 rescue.target runlevel1.target

A base system including mounting the filesystems with only the most basic services running and a rescue shell on the main console.

2   runlevel2.target

Multiuser, without NFS but all other non-GUI services running.

3 multi-user.target runlevel3.target

All services running but command line interface (CLI) only.

4   runlevel4.target

Unused.

5 graphical.target runlevel5.target

multi-user with a GUI.

6 reboot.target runlevel6.target

Reboot.

  default.target  

This target is always aliased with a symbolic link to either multi-user.target or graphical.target. systemd always uses the default.target to start the system. The default.target should never be aliased to halt.target, poweroff.target, or reboot.target.

Each target will specify dependencies in its configuration file. Dependencies can be started in the order in which they are started. If the relying party fails to start, the relying party fails to start (the relying party depends on the relying party). These dependencies are generally the services that the system needs to run at a certain level of functionality (such as web server, DB server, cache server, etc.). When all dependencies in the target configuration file are properly started, the system runs at that target level.

Systemd also looks for startup scripts in the SysV configuration directory, and if so, loads them. Basically on CentOS 7, services are already managed with system-d-style configuration files, but there is a network-related configuration file in the SysV configuration directory, which may be used as a learning case, or network services are still managed with SysV on CentOS 7 (with a low probability).

[[email protected] ~]# ls -l /etc/rc.d/init.d/
total 40
-rw-r--r--. 1 root root 18104 Jan  3  2018 functions
-rwxr-xr-x. 1 root root  4334 Jan  3  2018 netconsole
-rwxr-xr-x. 1 root root  7293 Jan  3  2018 network
-rw-r--r--. 1 root root  1160 Apr 11  2018 README

Next, let’s look at a text map, Figure 1. This image is from bootup (7). The startup process of system D is shown.

local-fs-pre.target
                    |
                    v
           (various mounts and   (various swap   (various cryptsetup
            fsck services...)     devices...)        devices...)       (various low-level   (various low-level
                    |                  |                  |             services: udevd,     API VFS mounts:
                    v                  v                  v             tmpfiles, random     mqueue, configfs,
             local-fs.target      swap.target     cryptsetup.target    seed, sysctl, ...)      debugfs, ...)
                    |                  |                  |                    |                    |
                    \__________________|_________________ | ___________________|____________________/
                                                         \|/
                                                          v
                                                   sysinit.target
                                                          |
                     ____________________________________/|\________________________________________
                    /                  |                  |                    |                    \
                    |                  |                  |                    |                    |
                    v                  v                  |                    v                    v
                (various           (various               |                (various          rescue.service
               timers...)          paths...)              |               sockets...)               |
                    |                  |                  |                    |                    v
                    v                  v                  |                    v              rescue.target
              timers.target      paths.target             |             sockets.target
                    |                  |                  |                    |
                    v                  \_________________ | ___________________/
                                                         \|/
                                                          v
                                                    basic.target
                                                          |
                     ____________________________________/|                                 emergency.service
                    /                  |                  |                                         |
                    |                  |                  |                                         v
                    v                  v                  v                                 emergency.target
                display-        (various system    (various system
            manager.service         services           services)
                    |             required for            |
                    |            graphical UIs)           v
                    |                  |           multi-user.target
|                  |                  |
                    \_________________ | _________________/
                                      \|/
                                       v
                             graphical.target

Sysinit. target and basic. target can be seen as a checkpoint. Although one of the design goals of system D is to start system services in parallel, there are still some specific services and targets that need to be started before other services and targets are started. The checkpoint will not pass until all the services and targets depended on by the checkpoint are satisfied.

Therefore, it is not possible to reach sysinit. target until all dependent units are completed. All those units mount the file system, configure swap files, start udev, set up random genorator seeds, initialize low-level devices, and configure encryption services if the file system needs to be encrypted. Within sysinit. target, however, these units can be executed in parallel. That is to say, system D supports parallel execution of units within a target.

Sysinit. target completes some of the underlying functions, that is, closer to the hardware layer, slowly moving to the higher level, close to the user layer, namely basic. target. The unit involved in this phase is shown in the figure.

Finally, you can start multi-user. target and graphical. target, two user-level targets that we are familiar with. Note: Multi-user. target must be started successfully before graphical. target can be started.

In Figure 1, the target with bold underline is a commonly used startup target, arriving at these targets means that the system has been started. After launching multi-user.target, the text-mode login interface is displayed, while graphical.target shows the graphical login interface. For more information about the graphical login interface, you can refer to Best Couple of 2016: Display Manager and Window Manager in Extended Reading.

 

Recommended Today

Write a package for parsing abnormal JSON strings – fbbk-json

F [beep] [beep] K JSON Parse a package of abnormal JSON strings. install $ npm install fbbk-json Use This package has only one function: var fJSON = require(“fbbk-json”); fJSON.parse(A_JSON_STRING); however This package supports the following JSON strings (that is, what we usually declare in javascript, without quotation marks). Raise a chestnut. ‘{foo”:”bar”,”baz”: true} < – […]