前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Linux】《how linux work》第五章 Linux内核的启动过程

【Linux】《how linux work》第五章 Linux内核的启动过程

作者头像
阿东
发布2024-04-10 08:24:38
2910
发布2024-04-10 08:24:38
举报
文章被收录于专栏:公众号:懒时小窝

Chapter 5. How the Linux Kernel Boots(第5章 Linux内核的启动过程)

You now know the physical and logical structure of a Linux system, what the kernel is, and how to work with processes. This chapter will teach you how the kernel starts— or boots. In other words, you’ll learn how the kernel moves into memory up to the point where the first user process starts.

你现在已经了解了Linux系统的物理和逻辑结构,知道了内核是什么,以及如何处理进程。

本章将教你内核是如何启动的。换句话说,你将学习内核如何将自己加载到内存中,直到第一个用户进程开始运行的过程。

A simplified view of the boot process looks like this:

启动过程的简化视图如下:

  1. The machine’s BIOS or boot firmware loads and runs a boot loader.
  2. The boot loader finds the kernel image on disk, loads it into memory, and starts it.
  3. The kernel initializes the devices and its drivers.
  4. The kernel mounts the root filesystem.
  5. The kernel starts a program called init with a process ID of 1. This point is the user space start.
  6. init sets the rest of the system processes in motion.
  7. At some point, init starts a process allowing you to log in, usually at the end or near the end of the boot.This chapter covers the first four stages, focusing on the kernel and boot loaders. Chapter 6 continues with the user space start.
  8. 计算机的BIOS或引导固件加载并运行引导加载程序。
  9. 引导加载程序在磁盘上找到内核镜像,将其加载到内存中并启动它。
  10. 内核初始化设备和驱动程序。
  11. 内核挂载根文件系统。
  12. 内核启动一个名为init的程序,它的进程ID为1。这一点是用户空间的起点。
  13. init启动其余的系统进程。
  14. 在某个时候,init启动一个进程,允许你登录,通常在启动结束或接近结束时。本章重点介绍前四个阶段,关注内核和引导加载程序。第6章将继续讲述用户空间的启动。

Your ability to identify each stage of the boot process will prove invaluable in fixing boot problems and understanding the system as a whole. However, the default behavior in many Linux distributions often makes it difficult, if not impossible, to identify the first few boot stages as they proceed, so you’ll probably be able to get a good look only after they’ve completed and you log in.

你能够识别启动过程的每个阶段对于解决启动问题和理解整个系统将非常有价值。

然而,许多Linux发行版的默认行为往往使得很难,甚至不可能在启动过程中识别前几个阶段的进行情况,所以你可能只能在它们完成并且你登录后才能仔细观察。

5.1 Startup Messages(启动信息)

Traditional Unix systems produce many diagnostic messages upon boot that tell you about the boot process. The messages come first from the kernel and then from processes and initialization procedures that init starts. However, these messages aren’t pretty or consistent, and in some cases they aren’t even very informative. Most current Linux distributions do their best to hide them with splash screens, filler, and boot options. In addition, hardware improvements have caused the kernel to start much faster than before; the messages flash by so quickly, it can be difficult to see what is happening.

传统的Unix系统在启动时会产生许多诊断消息,告诉你有关启动过程的信息。

这些消息首先来自内核,然后是由init启动的进程和初始化过程。

然而,这些消息并不美观或一致,有些情况下甚至不是很有信息量。

大多数当前的Linux发行版都会尽力隐藏这些消息,使用闪屏、填充物和启动选项。

此外,硬件的改进使得内核启动速度比以前快得多;消息闪过得非常快,很难看清楚正在发生什么。

There are two ways to view the kernel’s boot and runtime diagnostic messages. You can:

有两种方法可以查看内核的启动和运行时诊断消息。你可以:

o Look at the kernel system log file. You’ll often find this in /var/log/ kern.log, but depending on how your system is configured, it might also be lumped together with a lot of other system logs in /var/log/messages or elsewhere

o 查看内核系统日志文件。通常你会在/var/log/kern.log中找到它,但根据系统的配置方式,它也可能与许多其他系统日志一起存放在/var/log/messages或其他位置。

o Use the dmesg command, but be sure to pipe the output to less because there will be much more than a screen’s worth. The dmesg command uses the kernel ring buffer, which is of limited size, but most newer kernels have a large enough buffer to hold boot messages for a long time.

o 使用dmesg命令,但一定要将输出导入到less中,因为输出的内容可能远远超过一个屏幕的容量。

dmesg命令使用内核环形缓冲区,它的大小是有限的,但大多数较新的内核都有足够大的缓冲区来保存启动消息很长一段时间。

Here’s a sample of what you can expect to see from the dmesg command:

以下是你可以通过dmesg命令看到的示例:

代码语言:javascript
复制
$ dmesg[ 0.000000] Initializing cgroup subsys cpu  
[ 0.000000] Linux version 3.2.0-67-generic-pae (buildd@toyol) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #101-Ubuntu SMP Tue Jul 15 18:04:54 UTC 2014  
(Ubuntu 3.2.0-67.101-generic-pae 3.2.60)  
[ 0.000000] KERNEL supported cpus:  
--snip--  
[ 2.986148] sr0: scsi3-mmc drive: 24x/8x writer dvd-ram cd/rw xa/form2 cdda tray  
[ 2.986153] cdrom: Uniform CD-ROM driver Revision: 3.20  
[ 2.986316] sr 1:0:0:0: Attached scsi CD-ROM sr0  
[ 2.986416] sr 1:0:0:0: Attached scsi generic sg1 type 5  
[ 3.007862] sda: sda1 sda2 < sda5 >  
[ 3.008658] sd 0:0:0:0: [sda] Attached SCSI disk  
--snip--  

After the kernel has started, the user-space startup procedure often generates messages. These messages will likely be more difficult to view and review because on most systems you won’t find them in a single log file. Startup scripts usually print the messages to the console and they’re erased after the boot process finishes. However, this usually isn’t a problem because each script typically writes its own log. Some versions of init, such as Upstart and systemd, can capture diagnostic messages from startup and runtime that would normally go to the console.

内核启动后,用户空间启动过程通常会产生信息。

这些信息可能更难查看和审查,因为在大多数系统中,你不会在一个日志文件中找到它们。

启动脚本通常会将信息打印到控制台,并在启动过程结束后删除。

不过,这通常不是问题,因为每个脚本通常都会写入自己的日志。

某些版本的 init(如 Upstart 和 systemd)可以从启动和运行时捕获诊断信息,这些信息通常会传到控制台。

5.2 Kernel Initialization and Boot Options(内核初始化和启动选项)

Upon startup, the Linux kernel initializes in this general order:

在启动时,Linux内核按照以下一般顺序进行初始化:

  1. CPU inspection
  2. Memory inspection
  3. Device bus discovery
  4. Device discovery
  5. Auxiliary kernel subsystem setup (networking, and so on)
  6. Root filesystem mount
  7. User space start
  8. CPU检查
  9. 内存检查
  10. 设备总线发现
  11. 设备发现
  12. 辅助内核子系统设置(网络等)
  13. 挂载根文件系统
  14. 用户空间启动

The first steps aren’t too remarkable, but when the kernel gets to devices, a question of dependencies arises. For example, the disk device drivers may depend on bus support and SCSI subsystem support

前几个步骤并不太引人注目,但当内核到达设备时,就会出现依赖性的问题。

例如,磁盘设备驱动程序可能依赖于总线支持和SCSI子系统支持。

Later in the initialization process, the kernel must mount a root file-system before starting init. In general, you won’t have to worry about any of this, except that some necessary components may be loadable kernel modules rather than part of the main kernel. On some machines, you may need to load these kernel modules before the true root filesystem is mounted. We’ll cover this problem and its initial RAM filesystem workaround solutions in 6.8 The Initial RAM Filesystem.

在初始化过程的后期,内核必须在启动init之前挂载根文件系统。一般情况下,您不必担心这些问题,只是一些必要的组件可能是可加载的内核模块,而不是主内核的一部分。在某些机器上,您可能需要在真正的根文件系统挂载之前加载这些内核模块。我们将在6.8节“初始RAM文件系统”中介绍这个问题及其解决方法。

As of this writing, the kernel does not emit specific messages when it’s about to start its first user process. However, the following memory management messages are a good indication that the user-space handoff is about to happen because this is where the kernel protects its own memory from user-space processes:

截至本文撰写时,内核在即将启动其第一个用户进程时不会发出特定的消息。

但是,以下内存管理消息是一个很好的指示,表明即将发生用户空间的切换,因为这是内核保护自己内存免受用户空间进程影响的地方:

代码语言:javascript
复制
Freeing unused kernel memory: 740k freedWrite protecting the kernel text: 5820kWrite protecting the kernel read-only data: 2376kNX-protecting the kernel data: 4420k```  
  
You may also see a message about the root filesystem being mounted at this point.  
  
此时,您可能还会看到一条关于根文件系统已挂载的信息。  
  
> NOTE   
>   
> Feel free to skip ahead to Chapter 6 to learn the specifics of user space start and the init program that the kernel runs as its first process. The remainder of this chapter details how the kernel starts.  
         
> 注意 >   
> 请随意跳到第 6 章,了解用户空间启动和内核作为第一个进程运行的 init 程序的具体细节。
> 
> 本章其余部分将详细介绍内核的启动方式。  
# 5.3 Kernel Parameters(内核参数)  
  
When running the Linux kernel, the boot loader passes in a set of text-based kernel parameters that tell the kernel how it should start. The parameters specify many different types of behavior, such as the amount of diagnostic output the kernel should produce and device driver–specific options.  
  
在运行Linux内核时,引导加载程序会传递一组基于文本的内核参数,告诉内核它应该如何启动。

这些参数指定了许多不同类型的行为,例如内核应该产生多少诊断输出以及设备驱动程序特定的选项。  
  
You can view the kernel parameters from your system’s boot by looking at the /proc/cmdline file:  
  
您可以通过查看/proc/cmdline文件来查看系统启动时的内核参数。  
  
```sh  
$ cat /proc/cmdlineBOOT_IMAGE=/boot/vmlinuz-3.2.0-67-generic-pae root=UUID=70ccd6e7-6ae6-  
44f6-  
 812c-51aab8036d29 ro quiet splash vt.handoff=7```  
  
The parameters are either simple one-word flags, such as ro and quiet, or key=value pairs, such as vt.handoff=7. Many of the parameters are unimportant, such as the splash flag for displaying a splash screen, but one that is critical is the root parameter. This is the location of the root filesystem; without it, the kernel cannot find init and therefore cannot perform the user space start.  
  
这些参数要么是简单的单词标志,比如ro和quiet,要么是键值对,比如vt.handoff=7。

其中许多参数都不重要,比如用于显示启动画面的splash标志,但一个关键的参数是root参数。

这是根文件系统的位置;如果没有它,内核就找不到init,因此无法执行用户空间启动。  
  
The root filesystem can be specified as a device file, such as in this example:  
  
根文件系统可以指定为设备文件,例如在这个例子中:  
  
```sh  
root=/dev/sda1  

However, on most modern desktop systems, a UUID is more common (see 4.2.4 Filesystem UUID):

不过,在大多数现代桌面系统中,UUID 更为常见(参见 4.2.4 文件系统 UUID):

代码语言:javascript
复制
root=UUID=70ccd6e7-6ae6-44f6-812c-51aab80  

The ro parameter is normal; it instructs the kernel to mount the root filesystem in read-only mode upon user space start. (Read-only mode ensures that fsck can check the root filesystem safely; after the check, the bootup process remounts the root filesystem in read-write mode.)

ro参数是正常的;它指示内核在用户空间启动时以只读模式挂载根文件系统。

(只读模式确保fsck可以安全地检查根文件系统;检查完成后,启动过程会将根文件系统重新挂载为读写模式。)

Upon encountering a parameter that it does not understand, the Linux kernel saves the parameter. The kernel later passes the parameter to init when performing the user space start. For example, if you add -s to the kernel parameters, the kernel passes the -s to the init program to indicate that it should start in single-user mode.

当遇到无法理解的参数时,Linux内核会保存该参数。内核在执行用户空间启动时会将该参数传递给init。例如,如果您添加了-s到内核参数中,内核会将-s传递给init程序,表示应该以单用户模式启动。

Now let’s look at the mechanics of how boot loaders start the kernel.

现在让我们来看看引导加载程序如何启动内核的机制。

5.4 Boot Loaders (引导加载器 )

At the start of the boot process, before the kernel and init start, a boot loader starts the kernel. The task of a boot loader sounds simple: It loads the kernel into memory, and then starts the kernel with a set of kernel parameters. But consider the questions that the boot loader must answer:

在启动过程的开始阶段,在内核和init启动之前,引导加载程序会启动内核。

引导加载程序的任务听起来很简单:它将内核加载到内存中,然后使用一组内核参数启动内核。

但是请考虑引导加载程序必须回答的问题:

o Where is the kernel? o What kernel parameters should be passed to the kernel when it starts?

  • 内核在哪里?
  • 内核启动时应传递哪些内核参数?

The answers are (typically) that the kernel and its parameters are usually somewhere on the root filesystem. It sounds like the kernel parameters should be easy to find, except that the kernel is not yet running, so it can’t traverse a filesystem to find the necessary files. Worse, the kernel device drivers normally used to access the disk are also unavailable. Think of this as a kind of “chicken or egg” problem

答案(通常)是内核及其参数通常位于根文件系统的某个位置。

内核参数似乎应该很容易找到,但是由于内核尚未运行,因此无法遍历文件系统以找到必要的文件。更糟糕的是,通常用于访问磁盘的内核设备驱动程序也不可用。

可以将其视为一种“先有鸡还是先有蛋”的问题。

Let’s start with the driver concern. On PCs, boot loaders use the Basic Input/Output System (BIOS) or Unified Extensible Firmware Interface (UEFI) to access disks. Nearly all disk hardware has firmware that allows the BIOS to access attached storage hardware with Linear Block Addressing (LBA). Although it exhibits poor performance, this mode of access does allow universal access to disks. Boot loaders are often the only programs to use the BIOS for disk access; the kernel uses its own high-performance drivers.

让我们从驱动程序的问题开始。

在个人电脑上,引导加载程序使用基本输入/输出系统(BIOS)或统一可扩展固件接口(UEFI)来访问磁盘。

几乎所有磁盘硬件都有固件,允许BIOS使用线性块寻址(LBA)来访问连接的存储硬件。

尽管性能较差,但这种访问模式确实允许对磁盘进行通用访问。

引导加载程序通常是唯一使用BIOS进行磁盘访问的程序;内核使用自己的高性能驱动程序。

The filesystem question is trickier. Most modern boot loaders can read partition tables and have built-in support for read-only access to filesystems. Thus, they can find and read files. This capability makes it far easier to dynamically configure and enhance the boot loader. Linux boot loaders have not always had this capability; without it, configuring the boot loader was more difficult.

文件系统的问题更加棘手。大多数现代引导加载程序可以读取分区表,并具有对文件系统的只读访问的内置支持。

因此,它们可以找到并读取文件。这种能力使得动态配置和增强引导加载程序变得更加容易。Linux引导加载程序并不总是具备这种能力;在没有这种能力的情况下,配置引导加载程序更加困难。

5.4.1 Boot Loader Tasks (引导加载器任务 )

A Linux boot loader’s core functionality includes the ability to do the following:

o Select among multiple kernels. o Switch between sets of kernel parameters. o Allow the user to manually override and edit kernel image names and parameters (for example, to enter single-user mode). o Provide support for booting other operating systems.

Boot loaders have become considerably more advanced since the inception of the Linux kernel, with features such as history and menu systems, but the basic need has always been flexibility in kernel image and parameter selection. One interesting phenomenon is that certain needs have diminished. For example, because you can now perform an emergency or recovery boot partially or entirely from a USB storage device, you probably won’t have to worry about manually entering kernel parameters or going into single-user mode. But modern boot loaders offer more power than ever, which can be particularly handy if you’re building custom kernels or just want to tweak parameters.

Linux引导加载程序的核心功能包括以下几点:

o 在多个内核之间进行选择。 o 在不同的内核参数集之间切换。 o 允许用户手动覆盖和编辑内核映像的名称和参数(例如,进入单用户模式)。 o 提供引导其他操作系统的支持。

自Linux内核诞生以来,引导加载程序已经变得更加先进,具备了诸如历史记录和菜单系统等功能,但基本需求始终是灵活选择内核映像和参数。有一个有趣的现象是,某些需求已经减少。例如,由于现在可以部分或完全从USB存储设备进行紧急或恢复引导,您可能不再需要担心手动输入内核参数或进入单用户模式。但现代引导加载程序提供了比以往更强大的功能,这对于构建自定义内核或只是想调整参数的用户来说尤为方便。

5.4.2 Boot Loader Overview (引导加载器概述 )

Here are the main boot loaders that you may encounter, in order of popularity:

以下是您可能会遇到的主要引导加载程序,按受欢迎程度排序:

o GRUB. A near-universal standard on Linux systems o LILO. One of the first Linux boot loaders. ELILO is a UEFI version o SYSLINUX. Can be configured to run from many different kinds of filesystems o LOADLIN. Boots a kernel from MS-DOS o efilinux. A UEFI boot loader intended to serve as a model and reference for other UEFI boot loaders o coreboot (formerly LinuxBIOS). A high-performance replacement for the PC BIOS that can include a kernel o Linux Kernel EFISTUB. A kernel plugin for loading the kernel directly from the EFI/UEFI System Partition (ESP) found on recent systems

o GRUB。在Linux系统上几乎是标准配置 o LILO。最早的Linux引导加载程序之一。ELILO是UEFI版本 o SYSLINUX。可以配置为从许多不同类型的文件系统中运行 o LOADLIN。从MS-DOS引导内核 o efilinux。一种UEFI引导加载程序,旨在为其他UEFI引导加载程序提供模型和参考 o coreboot(以前称为LinuxBIOS)。用于替代PC BIOS的高性能版本,可以包含内核 o Linux Kernel EFISTUB。用于从最新系统上的EFI/UEFI系统分区(ESP)直接加载内核的内核插件

This book deals exclusively with GRUB. The rationale behind using other boot loaders is either that they are simpler to configure than GRUB or that they are faster.

本书仅涉及GRUB。使用其他引导加载程序的理由要么是它们比GRUB更简单配置,要么是它们更快。

To enter a kernel name and parameters, you first need to know how to get to a boot prompt. Unfortunately, this can sometimes be difficult to figure out because Linux distributions customize boot loader behavior and appearance to their hearts’ content.

要输入内核名称和参数,您首先需要知道如何进入引导提示符。不幸的是,有时候这可能很难弄清楚,因为Linux发行版会根据自己的喜好自定义引导加载程序的行为和外观。

The next sections tell you how to get to a boot prompt in order to enter a kernel name and parameters. Once you’re comfortable with that, you’ll see how to configure and install a boot loader.

接下来的几节将告诉您如何进入引导提示符以输入内核名称和参数。一旦您熟悉了这一点,您将看到如何配置和安装引导加载程序。

5.5 GRUB Introduction(GRUB 简介 )

GRUB stands for Grand Unified Boot Loader. We’ll cover GRUB 2; there is also an older version now called GRUB Legacy that is slowing falling out of use.

GRUB 是 Grand Unified Boot Loader 的缩写。我们将介绍 GRUB 2;还有一个旧版本,现在称为 GRUB Legacy,正在逐渐被淘汰。

One of GRUB’s most important capabilities is filesystem navigation that allows for much easier kernel image and configuration selection. One of the best ways to see this in action and to learn about GRUB in general is to look at its menu. The interface is easy to navigate, but there’s a good chance that you’ve never seen it. Linux distributions often do their best to hide the boot loader from you.

GRUB 最重要的功能之一是文件系统导航,可以更方便地选择内核映像和配置。查看 GRUB 菜单是了解 GRUB 功能的最佳方式之一。界面很容易浏览,但你很可能从未见过它。Linux 发行版通常会尽力向你隐藏引导加载器。

To access the GRUB menu, press and hold SHIFT when your BIOS or firmware startup screen first appears. Otherwise, the boot loader configuration may not pause before loading the kernel. Figure 5-1 shows the GRUB menu. Press ESC to temporarily disable the automatic boot timeout after the GRUB menu appears

要访问 GRUB 菜单,请在 BIOS 或固件启动屏幕首次出现时按住 SHIFT。否则,引导加载器配置可能不会在加载内核前暂停。图 5-1 显示了 GRUB 菜单。出现 GRUB 菜单后,按 ESC 键可暂时禁用自动启动超时功能

image.png

Figure 5-1. GRUB menu

图5-1. GRUB 菜单

Try the following to explore the boot loader:

尝试以下步骤来探索引导加载程序:

  1. Reboot or power on your Linux system.
  2. Hold down SHIFT during the BIOS/Firmware self-test and/or splash screen to get the GRUB menu.
  3. Press e to view the boot loader configuration commands for the default boot option. You should see something like Figure 5-2.
  4. 重新启动或开机您的 Linux 系统。
  5. 在 BIOS/固件自检和/或启动画面期间按住 SHIFT 键,以获取 GRUB 菜单。
  6. 按下 e 键查看默认引导选项的引导加载程序配置命令。您应该会看到类似于图5-2的内容。

image.png

Figure 5-2. GRUB configuration editor

图5-2. GRUB配置编辑器

This screen tells us that for this configuration, the root is set with a UUID, the kernel image is /boot/vmlinuz3.2.0-31-generic-pae, and the kernel parameters include ro, quiet, and splash. The initial RAM filesystem is /boot/initrd.img-3.2.0-31-generic-pae. But if you’ve never seen this sort of configuration before, you may find it somewhat confusing. Why are there multiple references to root, and why are they different? Why is insmod here? Isn’t that a Linux kernel feature normally run by udevd?

这个界面告诉我们,对于这个配置,根目录使用了一个UUID,内核映像文件是/boot/vmlinuz-3.2.0-31-generic-pae,内核参数包括ro、quiet和splash。初始RAM文件系统是/boot/initrd.img-3.2.0-31-generic-pae。但是如果你以前从未见过这种配置,可能会感到有些困惑。为什么有多个对根目录的引用,而且它们为什么不同?为什么这里有insmod命令?那不是udev守护进程通常运行的Linux内核特性吗?

The double-takes are warranted, because GRUB doesn’t really use the Linux kernel—it starts it. The configuration you see consists wholly of GRUB internal commands. GRUB really is an entirely separate world. The confusion stems from the fact that GRUB borrows terminology from many sources. GRUB has its own “kernel” and its own insmod command to dynamically load GRUB modules, completely independent of the Linux kernel. Many GRUB commands are similar to Unix shell commands; there’s even an ls command to list files.

这种困惑是正常的,因为GRUB并不真正使用Linux内核,而是启动它。你看到的配置完全由GRUB内部命令组成。GRUB实际上是一个完全独立的世界。困惑的原因在于GRUB借用了许多来源的术语。GRUB有自己的“内核”和自己的insmod命令,用于动态加载GRUB模块,完全独立于Linux内核。许多GRUB命令类似于Unix shell命令;甚至有一个ls命令用于列出文件。

But the most confusion comes from the use of the word root. To clear it up, there is one simple rule to follow when you’re looking for your system’s root filesystem: Only the root kernel parameter will be the root filesystem when you boot your system.

但是最令人困惑的是对于root这个词的使用。为了澄清这一点,在寻找系统的根文件系统时,只有root内核参数在系统启动时才是根文件系统。

In the GRUB configuration, that kernel parameter is somewhere after the image name of the linux command. Every other reference to root in the configuration is to the GRUB root, which exists only inside of GRUB. The GRUB “root” is the filesystem where GRUB searches for kernel and RAM filesystem image files. In Figure 5-2, the GRUB root is first set to a GRUB-specific device (hd0,msdos1). Then in the following command, GRUB searches for a particular UUID on a partition. If it finds that UUID, it sets the GRUB root to that partition.

在GRUB配置中,该内核参数位于linux命令的映像名称之后。配置中对root的其他引用都是指GRUB的root,它仅存在于GRUB内部。GRUB的“root”是GRUB用于搜索内核和RAM文件系统映像文件的文件系统。在图5-2中,GRUB的root首先设置为一个GRUB特定的设备(hd0,msdos1)。然后在随后的命令中,GRUB在一个分区上搜索特定的UUID。如果找到该UUID,它将把GRUB的root设置为该分区。

To wrap things up, the linux command’s first argument (/boot/vmlinuz-...) is the location of the Linux kernel image file. GRUB loads this file from the GRUB root. The initrd command is similar, specifying the file for the initial RAM filesystem

总结一下,linux命令的第一个参数(/boot/vmlinuz-...)是Linux内核映像文件的位置。GRUB从GRUB的root加载此文件。initrd命令类似,指定初始RAM文件系统的文件。

You can edit this configuration inside GRUB; doing so is usually the easiest way to temporarily fix an erroneous boot. To permanently fix a boot problem, you’ll need to change the configuration (see 5.5.2 GRUB Configuration), but for now, let’s go one step deeper and examine some GRUB internals with the commandline interface.

你可以在GRUB中编辑这个配置;这通常是暂时修复错误引导的最简单的方法。要永久修复引导问题,你需要更改配置(参见5.5.2 GRUB配置),但现在,让我们更深入地使用命令行界面来查看一些GRUB内部信息。

5.5.1 Exploring Devices and Partitions with the GRUB Command Line (使用 GRUB 命令行探索设备和分区 )

As you can see in Figure 5-2, GRUB has its own device-addressing scheme. For example, the first hard disk found is hd0, followed by hd1, and so on. But device assignments are subject to change. Fortunately, GRUB can search all partitions for a UUID in order to find the one where the kernel resides, as you just saw with the search command.

正如您在图5-2中所看到的,GRUB有自己的设备寻址方案。

例如,找到的第一个硬盘是hd0,接着是hd1,依此类推。但是设备分配可能会发生变化。

幸运的是,GRUB可以搜索所有分区的UUID,以找到内核所在的分区,就像您刚才用search命令看到的那样。

Listing Devices (列表设备)

To get a feel for how GRUB refers to the devices on your system, access the GRUB command line by pressing C at the boot menu or configuration editor. You should get the GRUB prompt:

为了了解GRUB如何引用您系统上的设备,请通过在启动菜单或配置编辑器中按下C键来访问GRUB命令行。您应该会看到GRUB提示符:

代码语言:javascript
复制
grub>  

You can enter any command here that you see in a configuration, but to get started, try a diagnostic command instead: ls. With no arguments, the output is a list of devices known to GRUB:

您可以在这里输入任何您在配置中看到的命令,但是为了开始,请尝试使用诊断命令代替:ls。

如果没有参数,输出将是一个已知于GRUB的设备列表:

代码语言:javascript
复制
grub> ls (hd0) (hd0,msdos1) (hd0,msdos5)  

In this case, there is one main disk device denoted by (hd0) and the partitions (hd0,msdos1) and (hd0,msdos5). The msdos prefix on the partitions tells you that the disk contains an MBR partition table; it would begin with gpt for GPT. (You will find even deeper combinations with a third identifier, where a BSD disklabel map resides inside a partition, but you won’t normally have to worry about this unless you’re running multiple operating systems on one machine.)

在本例中,有一个以 (hd0) 表示的主磁盘设备,以及 (hd0,msdos1) 和 (hd0,msdos5) 分区。分区上的 msdos 前缀表示磁盘包含 MBR 分区表;GPT 则以 gpt 开头。(你会发现带有第三个标识符的更深层次的组合,即 BSD 磁盘标签映射位于分区内部,但除非你在一台机器上运行多个操作系统,否则通常不必担心这个问题)。

To get more detailed information, use ls -l. This command can be particularly useful because it displays any UUIDs of the partitions on the disk. For example:

要获取更详细的信息,请使用 ls -l。该命令特别有用,因为它会显示磁盘上分区的 UUID。例如

代码语言:javascript
复制
grub> ls -l  
Device hd0: Not a known filesystem - Total size 426743808 sectors Partition hd0,msdos1: Filesystem type ext2 – Last modification time  
 2015-09-18 20:45:00 Friday, UUID 4898e145-b064-45bd-b7b4-7326b00273b7 -Partition start at 2048 - Total size 424644608 sectors Partition hd0,msdos5: Not a known filesystem - Partition start at 424648704 - Total size 2093056 sectors```  
  
This particular disk has a Linux ext2/3/4 filesystem on the first MBR partition and a Linux swap signature on partition 5, which is a fairly common configuration. (You can’t tell that (hd0,msdos5) is a swap partition from this output, though.)  
  
该磁盘的第一个 MBR 分区上有 Linux ext2/3/4 文件系统,第 5 分区上有 Linux swap 签名,这是一种相当常见的配置。(不过,从输出结果中看不出 (hd0,msdos5) 是交换分区)。  
  
### File Navigation  
  
Now let’s look at GRUB’s filesystem navigation capabilities. Determine the GRUB root with the echo command (recall that this is where GRUB expects to find the kernel):  
  
现在让我们看看 GRUB 的文件系统导航功能。使用 echo 命令确定 GRUB 根目录(请记住,这是 GRUB 希望找到内核的位置):  
  
  
```sh  
grub> echo $root  
hd0,msdos1  
  

To use GRUB’s ls command to list the files and directories in that root, you can append a forward slash to the end of the partition:

要使用 GRUB 的 ls 命令列出根目录下的文件和目录,可以在分区末尾添加一个斜线:

代码语言:javascript
复制
grub> ls (hd0,msdos1)/  

But it’s a pain to remember and type the actual root partition, so use the root variable to save yourself some time:

但记住并键入实际的 root 分区很麻烦,所以使用 root 变量可以节省时间:

代码语言:javascript
复制
grub> ls ($root)/  

The output is a short list of file and directory names on that partition’s filesystem, such as etc/, bin/, and dev/. You should realize that this is now a completely different function of the GRUB ls: Before, you were listing devices, partition tables, and perhaps some filesystem header information. Now you’re actually looking at the contents of filesystems.

You can take a deeper look into the files and directories on a partition in a similar manner. For example, to inspect the /boot directory, start with the following:

输出结果:

输出的是该分区文件系统上的文件和目录名称的简短列表,例如etc/,bin/和dev/。

您应该意识到,这是GRUB ls的完全不同的功能:之前,您是在列出设备、分区表,以及可能的一些文件系统头信息。现在,您实际上正在查看文件系统的内容。

您可以以类似的方式更深入地查看分区上的文件和目录。例如,要检查/boot目录,请从以下内容开始:

代码语言:javascript
复制
grub> ls ($root)/boot  
  

NOTE Use the up and down arrow keys to flip through GRUB command history and the left and right arrows to edit the current command line. The standard readline keys (CTRL-N, CTRL-P, and so on) also work. 注意:使用上下箭头键来翻阅GRUB命令历史记录,使用左右箭头键来编辑当前命令行。标准的readline键(CTRL-N、CTRL-P等)也可以使用。

You can also view all currently set GRUB variables with the set command:

您还可以使用set命令查看当前设置的所有GRUB变量。

代码语言:javascript
复制
grub> set  
?=0  
color_highlight=black/white  
color_normal=white/black  
--snip--  
prefix=(hd0,msdos1)/boot/grub  
root=hd0,msdos1  
  

One of the most important of these variables is $prefix, the filesystem and directory where GRUB expects to find its configuration and auxiliary support. We’ll explore this in the next section.

其中最重要的变量之一是$prefix,它是GRUB期望找到其配置和辅助支持的文件系统和目录。我们将在下一节中探讨这个问题。

Once you’ve finished with the GRUB command-line interface, enter the boot command to boot your current configuration or just press ESC to return to the GRUB menu. In any case, boot your system; we’re going to explore the GRUB configuration, and that’s best done when you have your full system available.

一旦你完成了GRUB命令行界面的操作,输入boot命令来启动当前的配置,或者按ESC键返回到GRUB菜单。无论哪种情况,都要启动你的系统;我们将要探索GRUB配置,而在你拥有完整的系统时进行这个操作是最好的。

5.5.2 GRUB Configuration (GRUB 配置 )

The GRUB configuration directory contains the central configuration file (grub.cfg) and numerous loadable modules with a .mod suffix. (As GRUB versions progress, these modules will move into subdirectories such as i386-pc.) The directory is usually /boot/grub or /boot/grub2. We won’t modify grub.cfg directly; instead, we’ll use the grub-mkconfig command (or grub2-mkconfig on Fedora).

GRUB 配置目录包含中央配置文件 (grub.cfg) 和许多后缀为 .mod 的可加载模块。

(随着 GRUB 版本的更新,这些模块将移至 i386-pc 等子目录)。

该目录通常为 /boot/grub 或 /boot/grub2。我们不会直接修改 grub.cfg,而是使用 grub-mkconfig 命令(或 Fedora 上的 grub2-mkconfig)。

Reviewing Grub.cfg (查看 Grub.cfg )

First, take a quick look at grub.cfg to see how GRUB initializes its menu and kernel options. You’ll see that the grub.cfg file consists of GRUB commands, which usually begin with a number of initialization steps followed by a series of menu entries for different kernel and boot configurations. The initialization isn’t complicated; it’s a bunch of function definitions and video setup commands like this:

首先,快速查看grub.cfg文件,了解GRUB如何初始化其菜单和内核选项。

您会发现grub.cfg文件由一系列GRUB命令组成,通常以一系列初始化步骤开始,然后是一系列不同内核和引导配置的菜单条目。

初始化过程并不复杂;它包括一些函数定义和视频设置命令,例如:

代码语言:javascript
复制
if loadfont /usr/share/grub/unicode.pf2 ; then  
 set gfxmode=auto load_video insmod gfxterm --snip--  

Later in this file you should see the available boot configurations, each beginning with the menuentry command. You should be able to read and understand this example based on what you learned in the preceding section:

在本文件的稍后部分,您将看到可用的启动配置,每个配置都以 menuentry 命令开头。根据上一节所学内容,您应该能够阅读并理解本示例:

代码语言:javascript
复制
menuentry 'Ubuntu, with Linux 3.2.0-34-generic-pae' --class ubuntu --class gnu-linux --class gnu--class os { recordfail  
 gfxmode $linux_gfx_mode insmod gzio insmod part_msdos insmod ext2 set root='(hd0,msdos1)' search --no-floppy --fs-uuid --set=root 70ccd6e7-6ae6-44f6-812c51aab8036d29 linux /boot/vmlinuz-3.2.0-34-generic-pae root=UUID=70ccd6e7-6ae6-44f6-812c-51aab8036d29  
 ro quiet splash $vt_handoff initrd /boot/initrd.img-3.2.0-34-generic-pae}  
  

Watch for submenu commands. If your grub.cfg file contains numerous menuentry commands, most of them are probably wrapped up inside a submenu command for older versions of the kernel so that they don’t crowd the GRUB menu.

请注意子菜单命令。如果您的grub.cfg文件包含大量的menuentry命令,其中大部分可能被包裹在一个子菜单命令中,用于旧版本的内核,以避免拥挤GRUB菜单。

Generating a New Configuration File ( 生成新配置文件 )

If you want to make changes to your GRUB configuration, you won’t edit your grub.cfg file directly because it’s automatically generated and the system occasionally overwrites it. You’ll add your new configuration elsewhere, then run grub-mkconfig to generate the new configuration.

如果您想对GRUB配置进行更改,不要直接编辑grub.cfg文件,因为它是自动生成的,系统有时会覆盖它。您可以在其他地方添加新的配置,然后运行grub-mkconfig来生成新的配置。

To see how the configuration generation works, look at the very beginning of grub.cfg. There should be comment lines such as this:

要了解配置生成的工作原理,请查看grub.cfg的开头部分。应该有类似以下的注释行:

代码语言:javascript
复制
### BEGIN /etc/grub.d/00_header ###  

Upon further inspection, you’ll find that every file in /etc/grub.d is a shell script that produces a piece of the grub.cfg file. The grub-mkconfig command itself is a shell script that runs everything in /etc/grub.d.

经过进一步检查,您会发现/etc/grub.d目录中的每个文件都是一个Shell脚本,用于生成grub.cfg文件的一部分。grub-mkconfig命令本身也是一个Shell脚本,运行/etc/grub.d目录中的所有内容。

Try it yourself as root. (Don’t worry about overwriting your current configuration. This command by itself simply prints the configuration to the standard output.)

作为root用户,您可以尝试一下。(不用担心覆盖当前配置。这个命令只会将配置信息打印到标准输出。)

代码语言:javascript
复制
# grub-mkconfig  

The long answer is a little more complicated. The /etc/grub.d configuration directory gives you two options: 40_custom and 41_custom. The first, 40_custom, is a script that you can edit yourself, but it’s probably the least stable; a package upgrade is likely to destroy any changes you make. The 41_custom script is simpler; it’s just a series of commands that load custom.cfg when GRUB starts. (Keep in mind that if you choose this second option, your changes won’t appear when you generate your configuration file.)

The two options for custom configuration files aren’t particularly extensive. You’ll see additions in your particular distribution’s /etc/grub.d directory. For example, Ubuntu adds memory tester boot options (memtest86+) to the configuration.

To write and install a newly generated GRUB configuration file, you can write the configuration to your GRUB directory with the -o option to grub-mkconfig, like this:

长答案稍微复杂一些。/etc/grub.d配置目录提供了两个选项:40_custom和41_custom。第一个选项40_custom是一个你可以自己编辑的脚本,但它可能是最不稳定的;升级软件包可能会破坏你所做的任何更改。41_custom脚本更简单;它只是一系列在GRUB启动时加载custom.cfg的命令。(请记住,如果选择第二个选项,生成配置文件时你的更改将不会显示。)

自定义配置文件的两个选项并不是特别广泛。你会在你特定的发行版的/etc/grub.d目录中看到添加的内容。例如,Ubuntu在配置中添加了内存测试程序的启动选项(memtest86+)。

要编写和安装新生成的GRUB配置文件,你可以使用grub-mkconfig命令的-o选项将配置写入你的GRUB目录,像这样:

代码语言:javascript
复制
# grub-mkconfig -o /boot/grub/grub.cfg  

Or if you’re an Ubuntu user, just run install-grub. In any case, back up your old configuration, make sure that you’re installing to the correct directory, and so on.

Now we’re going to get into some of the more technical details of GRUB and boot loaders. If you’re tired of hearing about boot loaders and the kernel, feel free to skip to Chapter 6.

如果你是一个Ubuntu用户,只需运行install-grub命令。无论如何,请备份您的旧配置,确保您安装到了正确的目录等等。

现在我们将进入一些关于GRUB和引导加载程序的更多技术细节。如果你厌倦了听关于引导加载程序和内核的内容,可以跳到第6章。

5.5.3 GRUB Installation (GRUB 安装 )

Installing GRUB is more involved than configuring it. Fortunately, you won’t normally have to worry about installation because your distribution should handle it for you. However, if you’re trying to duplicate or restore a bootable disk, or preparing your own boot sequence, you might need to install it on your own

安装GRUB比配置它更复杂。幸运的是,通常情况下,您不必担心安装问题,因为您的发行版应该会为您处理。然而,如果您想要复制或恢复可引导的磁盘,或者准备自己的引导顺序,您可能需要自己安装它。

Before proceeding, read 5.8.3 How GRUB Works to get an idea of how PCs boot and determine whether you’re using MBR or EFI boot. Next, build the GRUB software set and determine where your GRUB directory will be; the default is /boot/grub. You may not need to build GRUB if your distribution does it for you, but if you do, see Chapter 16 for how to build software from source code. Make sure that you build the correct target: It’s different for MBR or UEFI boot (and there are even differences between 32-bit and 64-bit EFI).

在继续之前,请阅读5.8.3 GRUB的工作原理,了解个人电脑的引导方式,并确定您是使用MBR还是EFI引导。

接下来,构建GRUB软件集,并确定您的GRUB目录位置;默认位置是/boot/grub。如果您的发行版已经为您构建了GRUB,您可能不需要自己构建,但如果需要,请参考第16章中的如何从源代码构建软件的方法。

确保构建正确的目标:MBR引导和UEFI引导是不同的(甚至32位和64位EFI之间也有区别)。

Installing GRUB on Your System ( 在系统上安装 GRUB)

Installing the boot loader requires that you or an installer determine the following:

安装引导加载程序需要您或安装程序确定以下内容:

o The target GRUB directory as seen by your currently running system. That’s usually /boot/grub, but it might be different if you’re installing GRUB on another disk for use on another system. o The current device of the GRUB target disk. o For UEFI booting, the current mount point of the UEFI boot partition

o 目标 GRUB 目录,由您当前正在运行的系统所看到。通常是 /boot/grub,但如果您要在另一个磁盘上安装 GRUB 以供另一个系统使用,则可能会有所不同。 o GRUB 目标磁盘的当前设备。 o 对于 UEFI 引导,UEFI 引导分区的当前挂载点。

Remember that GRUB is a modular system, but in order to load modules, it must read the filesystem that contains the GRUB directory. Your task is to construct a version of GRUB capable of reading that filesystem so that it can load the rest of its configuration (grub.cfg) and any required modules. On Linux, this usually means building a version of GRUB with its ext2.mod module preloaded. Once you have this version, all you need to do is place it on the bootable part of the disk and place the rest of the required files into /boot/grub.

请记住,GRUB 是一个模块化的系统,但为了加载模块,它必须读取包含 GRUB 目录的文件系统。

您的任务是构建一个能够读取该文件系统的 GRUB 版本,以便它可以加载其余的配置文件(grub.cfg)和任何所需的模块。

在 Linux 上,这通常意味着构建一个预加载了 ext2.mod 模块的 GRUB 版本。

一旦您拥有了这个版本,您只需要将它放置在可引导的磁盘上,并将其余所需文件放置在 /boot/grub 目录中。

Fortunately, GRUB comes with a utility called grub-install (not to be confused with Ubuntu’s install-grub), which performs most of the work of installing the GRUB files and configuration for you. For example, if your current disk is at /dev/sda and you want to install GRUB on that disk with your current /boot/grub directory, use this command to install GRUB on the MBR:

幸运的是,GRUB 自带一个名为 grub-install 的实用程序(不要与 Ubuntu 的 install-grub 混淆),它可以为您执行大部分安装 GRUB 文件和配置的工作。

例如,如果您当前的磁盘位于 /dev/sda,并且您想要将 GRUB 安装在该磁盘上,使用当前的 /boot/grub 目录,可以使用以下命令在 MBR 上安装 GRUB:

代码语言:javascript
复制
# grub-install /dev/sda  

WARNING Incorrectly installing GRUB may break the bootup sequence on your system, so don’t take this command lightly. If you’re concerned, read up on how to back up your MBR with dd, back up any other currently installed GRUB directory, and make sure that you have an emergency bootup plan. 警告 > 错误安装 GRUB 可能会破坏系统的启动顺序,因此不要轻易执行此命令。 如果担心,请阅读如何使用 dd 备份 MBR,备份当前安装的任何其他 GRUB 目录,并确保有一个紧急启动计划。

Installing GRUB on an External Storage Device (在外部存储设备上安装 GRUB )

To install GRUB on a storage device outside the current system, you must manually specify the GRUB directory on that device as your current system now sees it. For example, say that you have a target device of /dev/sdc and that device’s root/boot filesystem (for example, /dev/sdc1) is mounted on /mnt of your current system. This implies that when you install GRUB, your current system will see the GRUB files in /mnt/boot/grub. When running grub-install, tell it where those files should go as follows:

要在当前系统外的存储设备上安装GRUB,您必须手动指定该设备上的GRUB目录,以便您的当前系统能够看到它。

例如,假设您的目标设备是/dev/sdc,并且该设备的根/引导文件系统(例如,/dev/sdc1)被挂载在当前系统的/mnt目录下。

这意味着当您安装GRUB时,您的当前系统将在/mnt/boot/grub中看到GRUB文件。

在运行grub-install时,告诉它这些文件应该放在哪里,如下所示:

代码语言:javascript
复制
# grub-install --boot-directory=/mnt/boot /dev/sdc  
  

Installing GRUB with UEFI (使用 UEFI 安装 GRUB )

UEFI installation is supposed to be easier, because you all you need to do is copy the boot loader into place. But you also need to “announce” the boot loader to the firmware with the efibootmgr command. The grub-install command runs this if it’s available, so in theory all you need to do to install on an UEFI partition is the following:

UEFI安装应该更加简单,因为你只需要将引导加载程序复制到正确的位置即可。

但是你还需要使用efibootmgr命令将引导加载程序“通知”给固件。

如果可用,grub-install命令会自动运行此操作,所以理论上,你只需要执行以下步骤即可在UEFI分区上进行安装:

代码语言:javascript
复制
# grub-install --efi-directory=efi_dir –-bootloader-id=name  

Here, efi_dir is where the UEFI directory appears on your current system (usually /boot/efi/efi, because the UEFI partition is often mounted at /boot/efi) and name is an identifier for the boot loader, as described in 5.8.2 UEFI Boot

在这里,efi_dir是UEFI目录在您当前系统上的位置(通常是/boot/efi/efi,因为UEFI分区通常被挂载在/boot/efi上),name是引导加载程序的标识符,如5.8.2 UEFI引导中所述。

Unfortunately, many problems can crop up when installing a UEFI boot loader. For example, if you’re installing to a disk that will eventually end up in another system, you have to figure out how to announce that boot loader to the new system’s firmware. And there are differences in the install procedure for removable media.

不幸的是,在安装UEFI引导加载程序时可能会出现许多问题。

例如,如果您要安装到最终会进入另一个系统的磁盘上,您必须找出如何向新系统的固件通告该引导加载程序。

而且,可移动介质的安装过程也有所不同。

But one of the biggest problems is UEFI secure boot.

但是,其中最大的问题之一就是UEFI安全启动。

5.6 UEFI Secure Boot Problems (UEFI 安全启动问题 )

One of the newest problems affecting Linux installations is the secure boot feature found on recent PCs. When active, this mechanism in UEFI requires boot loaders to be digitally signed by a trusted authority in order to run. Microsoft has required vendors shipping Windows 8 to use secure boot. The result is that if you try to install an unsigned boot loader (which is most current Linux distributions), it will not load.

最新影响Linux安装的问题之一是最近PC上出现的安全启动功能。当激活时,UEFI中的这种机制要求引导加载程序必须由可信任的机构进行数字签名才能运行。微软要求出货的Windows 8设备使用安全启动。结果就是,如果你尝试安装未经签名的引导加载程序(大多数当前的Linux发行版都是如此),它将无法加载。

The easiest way around this for anyone with no interest in Windows is to disable secure boot in the EFI settings. However, this won’t work cleanly for dual-boot systems and may not be an option for all users. Therefore, Linux distributions are offering signed boot loaders. Some solutions are just front-ends to GRUB, some offer a fully signed loading sequence (from the boot loader to the kernel), and others are entirely new boot loaders (some based on efilinux).

对于那些对Windows没有兴趣的用户来说,最简单的方法是在EFI设置中禁用安全启动。

然而,这对于双启动系统来说可能不太方便,并且可能并非所有用户的选择。

因此,Linux发行版提供了经过签名的引导加载程序。有些解决方案只是GRUB的前端,有些提供了完全经过签名的加载顺序(从引导加载程序到内核),还有一些是全新的引导加载程序(一些基于efilinux)。

5.7 Chainloading Other Operating Systems(链载其他操作系统 )

UEFI makes it relatively easy to support loading other operating systems because you can install multiple boot loaders in the EFI partition. However, the older MBR style doesn’t support it, and even if you do have UEFI, you may still have an individual partition with an MBR-style boot loader that you want to use. You can get GRUB to load and run a different boot loader on a specific partition on your disk by chainloading

UEFI使得支持加载其他操作系统相对容易,因为你可以在EFI分区中安装多个引导加载程序。

然而,旧的MBR样式不支持此功能,即使你有UEFI,你可能仍然有一个使用MBR样式引导加载程序的单独分区,你想要使用它。

通过链式加载,你可以让GRUB在磁盘上的特定分区上加载和运行不同的引导加载程序。

To chainload, create a new menu entry in your GRUB configuration (using one of the methods in Reviewing Grub.cfg). Here’s an example for a Windows installation on the third partition of a disk:

要进行链式加载,可以在GRUB配置中创建一个新的菜单项(使用“Reviewing Grub.cfg”中的方法之一)。以下是一个示例,用于在磁盘的第三个分区上安装Windows:

代码语言:javascript
复制
menuentry "Windows" { insmod chain insmod ntfs set root=(hd0,3) chainloader +1}  

The +1 option to chainloader tells it to load whatever is at the first sector of a partition. You can also get it to directly load a file by using a line like this to load the io.sys MS-DOS loader:

chainloader 的 +1 选项会告诉它加载分区第一个扇区的任何内容。你也可以用这样一行来加载 io.sys MS-DOS 加载器,让它直接加载文件:

代码语言:javascript
复制
menuentry "DOS" { insmod chain insmod fat set root=(hd0,3) chainloader /io.sys}  

5.8 Boot Loader Details (引导加载器详细信息 )

Now we’ll look quickly at some boot loader internals. Feel free to skip to the next chapter if this material doesn’t interest you.

现在我们将简要介绍一些引导加载程序的内部机制。

如果这部分内容不符合您的兴趣,可以跳到下一章节。

To understand how boot loaders like GRUB work, let’s first survey how a PC boots when you turn it on. Due to the repeated inadequacies of traditional PC boot mechanisms, there are several variations, but there are two main schemes: MBR and UEFI

为了理解像GRUB这样的引导加载程序是如何工作的,让我们首先了解一下当您打开计算机电源时,计算机是如何启动的。

由于传统PC引导机制的重复不足,存在几种变体,但主要有两种方案:MBR和UEFI。

5.8.1 MBR Boot (MBR 启动 )

In addition to the partition information described in 4.1 Partitioning Disk Devices, the Master Boot Record (MBR) includes a small area (441 bytes) that the PC BIOS loads and executes after its Power-On Self-Test (POST). Unfortunately, this is too little storage to house almost any boot loader, so additional space is necessary, resulting in what is sometimes called a multi-stage boot loader. In this case the initial piece of code in the MBR does nothing other than load the rest of the boot loader code. The remaining pieces of the boot loader are usually stuffed into the space between the MBR and the first partition on the disk.

除了 4.1 磁盘设备分区中描述的分区信息外,主引导记录 (MBR) 还包括一小块区域(441 字节),用于 PC BIOS 在开机自检 (POST) 后加载和执行。

不幸的是,这个存储空间太小,几乎无法容纳任何引导加载程序,因此需要额外的空间,这就是所谓的多阶段引导加载程序。在这种情况下,MBR 中的初始代码除了加载引导加载器的其他代码外没有其他作用。

引导加载器的其余部分通常被塞入 MBR 和磁盘上第一个分区之间的空间。

Of course, this isn’t terribly secure because anything can overwrite the code there, but most boot loaders do it, including most GRUB installations. In addition, this scheme won’t work with a GPT-partitioned disk using the BIOS to boot because the GPT table information resides in the area after the MBR. (GPT leaves the traditional MBR alone for backward compatibility.)

当然,这并不是非常安全,因为任何东西都可以覆盖那里的代码,但大多数引导加载器都是这样做的,包括大多数 GRUB 安装。

此外,该方案不能用于使用 BIOS 启动的 GPT 分区磁盘,因为 GPT 表信息位于 MBR 之后的区域。(为了向后兼容,GPT 只保留了传统的 MBR)。

The workaround for GPT is to create a small partition called a BIOS boot partition with a special UUID to give the full boot loader code a place to reside. But GPT is normally used with UEFI, not the traditional BIOS, which leads us to the UEFI boot scheme.

GPT 的变通方法是创建一个称为 BIOS 启动分区的小分区,该分区具有特殊的 UUID,以便为完整的启动加载程序代码提供存放位置。

但 GPT 通常用于 UEFI,而不是传统的 BIOS,这就引出了 UEFI 启动方案。

5.8.2 UEFI Boot( UEFI 启动 )

PC manufacturers and software companies realized that the traditional PC BIOS is severely limited, so they decided to develop a replacement called Extensible Firmware Interface (EFI). EFI took a while to catch on for most PCs, but now it’s fairly common. The current standard is Unified EFI (UEFI), which includes features such as a built-in shell and the ability to read partition tables and navigate filesystems. The GPT partitioning scheme is part of the UEFI standard.

个人电脑制造商和软件公司意识到,传统的个人电脑 BIOS 有很大的局限性,因此他们决定开发一种名为 "可扩展固件接口"(EFI)的替代品。

EFI 花了一段时间才被大多数个人电脑所接受,但现在已经相当普遍。

目前的标准是统一 EFI (UEFI),它包括一些功能,如内置 shell 以及读取分区表和浏览文件系统的能力。GPT 分区方案是 UEFI 标准的一部分。

Booting is radically different on UEFI systems and, for the most part, much easier to understand. Rather than executable boot code residing outside of a filesystem, there is always a special filesystem called the EFI System Partition (ESP), which contains a directory named efi. Each boot loader has its own identifier and a corresponding subdirectory, such as efi/microsoft, efi/apple, or efi/grub. A boot loader file has an .efi extension and resides in one of these subdirectories, along with other supporting files.

在 UEFI 系统上,启动方式截然不同,而且大部分情况下更容易理解。

在 UEFI 系统中,可执行的启动代码并不存在于文件系统之外,而是始终存在一个名为 EFI 系统分区(ESP)的特殊文件系统,其中包含一个名为 efi 的目录。

每个引导加载程序都有自己的标识符和相应的子目录,如 efi/microsoft、efi/apple 或 efi/grub。

Boot Loader 文件的扩展名为 .efi,与其他支持文件一起存放在这些子目录中。

NOTE The ESP differs from the BIOS boot partition described in 5.8.1 MBR Boot and has a different UUID. 注意 ESP 与 5.8.1 MBR 启动中描述的 BIOS 启动分区不同,其 UUID 也不同。

There’s a wrinkle, though: You can’t just put old boot loader code into the ESP because that code was written for the BIOS interface. Instead, you must provide a boot loader written for UEFI. For example, when using GRUB, you have to install the UEFI version of GRUB rather than the BIOS version. In addition, you must “announce” new boot loaders to the firmware.

但有一个问题:不能将旧的引导加载程序代码放入 ESP,因为这些代码是为 BIOS 界面编写的。

相反,你必须提供一个为 UEFI 编写的引导加载器。

例如,在使用 GRUB 时,必须安装 UEFI 版本的 GRUB 而不是 BIOS 版本。

此外,您必须向固件 "宣布 "新的启动加载程序。

And, as mentioned in 5.6 UEFI Secure Boot Problems, we have the “secure boot” issue.

正如 5.6 UEFI 安全启动问题中提到的,我们还有 "安全启动 "问题。

5.8.3 How GRUB Works (GRUB 如何工作 )

Let’s wrap up our discussion of GRUB by looking at how it does its work:

最后,我们来看看 GRUB 是如何工作的:

  1. The PC BIOS or firmware initializes the hardware and searches its boot-order storage devices for boot code.
  2. Upon finding the boot code, the BIOS/firmware loads and executes it. This is where GRUB begins.
  3. The GRUB core loads.
  4. The core initializes. At this point, GRUB can now access disks and filesystems.
  5. GRUB identifies its boot partition and loads a configuration there.
  6. GRUB gives the user a chance to change the configuration.
  7. After a timeout or user action, GRUB executes the configuration (the sequence of commands outlined in 5.5.2 GRUB Configuration).
  8. In the course of executing the configuration, GRUB may load additional code (modules) in the boot partition.
  9. GRUB executes a boot command to load and execute the kernel as specified by the configuration’s linux command.
  10. 电脑 BIOS 或固件初始化硬件,并搜索启动顺序存储设备以获取启动代码。
  11. 找到启动代码后,BIOS/固件加载并执行它。这就是 GRUB 的开始。
  12. 加载 GRUB 核心。
  13. 核心初始化。此时,GRUB 可以访问磁盘和文件系统。
    1. GRUB 识别其引导分区并在此加载配置。
  14. GRUB 允许用户更改配置。
  15. 超时或用户操作后,GRUB 执行配置(5.5.2 GRUB 配置中概述的命令序列)。 5.5.2 GRUB 配置)。
  16. 在执行配置的过程中,GRUB 可能会在引导分区中加载额外的代码(模块)。 分区中的附加代码(模块)。
  17. GRUB 执行启动命令,加载并执行配置的 linux 命令指定的内核。

Steps 3 and 4 of the preceding sequence, where the GRUB core loads, can be complicated due to the repeated inadequacies of traditional PC boot mechanisms. The biggest question is “Where is the GRUB core?” There are three basic possibilities:

由于传统 PC 启动机制屡屡出现缺陷,前述序列中 GRUB 内核加载的第 3 步和第 4 步可能会变得复杂。

最大的问题是 "GRUB 内核在哪里?有三种基本可能性:

o Partially stuffed between the MBR and the beginning of the first partition o In a regular partition o In a special boot partition: a GPT boot partition, EFI System Partition (ESP), or elsewhere

o 部分塞在 MBR 和第一个分区的开头之间 o 常规分区中 o 在特殊引导分区中:GPT 引导分区、ESP 系统分区或其他地方

In all cases except where you have an ESP, the PC BIOS loads 512 bytes from the MBR, and that is where GRUB starts. This little piece (derived from boot.img in the GRUB directory) isn’t yet the core, but it contains the start location of the core and loads the core from this point

除 ESP 外,在所有情况下,电脑 BIOS 都会从 MBR 中加载 512 字节,这就是 GRUB 的起始位置。这一小段(来自 GRUB 目录中的 boot.img)还不是核心,但它包含了核心的起始位置,并从此处加载核心。

However, if you have an ESP, the GRUB core goes there as a file. The firmware can navigate the ESP and directly execute the GRUB core or any other operating system loader located there.

不过,如果你有一个 ESP,GRUB 内核就会以文件形式存在。

固件可以浏览 ESP 并直接执行 GRUB 内核或位于其中的任何其他操作系统加载器。

Still, on most systems, this is not the complete picture. The boot loader might also need to load an initial RAM filesystem image into memory before loading and executing the kernel. That’s what the initrd configuration parameter in 6.8 The Initial RAM Filesystem specifies. But before you learn about the initial RAM filesystem, you should learn about the user space start—that’s where the next chapter begins.

不过,在大多数系统中,这还不是全部。在加载和执行内核之前,引导加载器可能还需要将初始 RAM 文件系统映像加载到内存中。

这就是 6.8 初始 RAM 文件系统中的 initrd 配置参数所指定的。

但在了解初始 RAM 文件系统之前,你应该先了解用户空间的启动--这也是下一章的主题。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 懒时小窝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Chapter 5. How the Linux Kernel Boots(第5章 Linux内核的启动过程)
  • 5.1 Startup Messages(启动信息)
  • 5.2 Kernel Initialization and Boot Options(内核初始化和启动选项)
  • 5.4 Boot Loaders (引导加载器 )
    • 5.4.1 Boot Loader Tasks (引导加载器任务 )
      • 5.4.2 Boot Loader Overview (引导加载器概述 )
      • 5.5 GRUB Introduction(GRUB 简介 )
        • 5.5.1 Exploring Devices and Partitions with the GRUB Command Line (使用 GRUB 命令行探索设备和分区 )
          • Listing Devices (列表设备)
        • 5.5.2 GRUB Configuration (GRUB 配置 )
          • Reviewing Grub.cfg (查看 Grub.cfg )
          • Generating a New Configuration File ( 生成新配置文件 )
        • 5.5.3 GRUB Installation (GRUB 安装 )
          • Installing GRUB on an External Storage Device (在外部存储设备上安装 GRUB )
          • Installing GRUB with UEFI (使用 UEFI 安装 GRUB )
          • 5.8.1 MBR Boot (MBR 启动 )
          • 5.8.2 UEFI Boot( UEFI 启动 )
          • 5.8.3 How GRUB Works (GRUB 如何工作 )
      • 5.6 UEFI Secure Boot Problems (UEFI 安全启动问题 )
      • 5.7 Chainloading Other Operating Systems(链载其他操作系统 )
      • 5.8 Boot Loader Details (引导加载器详细信息 )
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档