引导加载程序存储在哪里 - 是存储在只读存储器(ROM)、随机存取存储器(RAM)还是其他地方?

根据维基百科的条目,引导加载程序是存储在只读存储器(ROM)中的一个小程序(主内存(RAM)的一部分,对吗?)。我有点困惑。这是否意味着我们购买的每个RAM都默认安装了引导加载程序? 另外,我从一本书中读到说硬盘上通常有一个被称为MBR(主引导记录)的区域,其中包括一个引导加载程序...
那么这个引导加载程序究竟位于哪里?不同的操作系统是否将其存储在不同的位置?
7个回答

ROM是与RAM分开的芯片。它不需要电源来保持其内容,并且最初无法通过任何方式进行修改,而是从工厂中硬连线。后来,可编程只读存储器(PROM)取代了真正的ROM。这些芯片从工厂出厂时是空白的,可以使用特殊程序写入一次,该程序实际上会烧毁芯片的位,导致其状态发生变化。然后,EPROM(可擦除可编程存储器)取代了PROM。这些芯片上有一个小窗口,如果将紫外线照射到其中,可以擦除它们,使其可以再次编程。然后,EEPROM(电可擦除可编程存储器)取代了EPROM。这些芯片具有特殊的软件程序,可以擦除它们以便重新编程。通常,ROM仍然用于泛指所有这些类型。
主板上有一种ROM芯片,用于保存固件,在个人电脑术语中通常称为BIOS(基本输入输出系统),尽管现在正在逐渐被EFI固件所取代。这是CPU在开机时首先执行的软件。所有固件都执行硬件初始化,通常提供一些诊断输出,并提供用户配置硬件的方法,然后定位并加载引导加载程序,引导加载程序再定位并加载操作系统。
使用PC BIOS,它只是加载并执行决定启动的磁盘的第一个扇区,通常是检测到的第一个硬盘。按照惯例,硬盘的第一个扇区称为主引导记录(MBR),其中包含DOS分区表,列出了磁盘上分区的位置,并留出一些空间用于引导加载程序。Ubuntu使用GRUB引导加载程序,在MBR中放置足够的代码来加载和执行/boot/grub/core.img。通常,该文件的副本被放置在MBR之后、第一个分区之前的扇区中,实际上这就是MBR加载的内容,因为在MBR中可用的空间非常有限,很难正确找到/boot/grub/core.img的位置。
grub核心映像包含基本的grub代码,以及访问/boot/grub所需的任何模块,以便它可以在那里加载其他模块,以及描述可以引导哪些操作系统以及它们的位置的grub配置文件。
Intel Mac上使用的EFI固件,并且作为最近大多数PC主板上BIOS的替代品而变得可用,需要一个专用分区来保存引导加载程序文件,而且固件足够智能,可以找到这些文件并加载其中一个,而不仅仅是加载和执行磁盘的第一个扇区中的内容。

这是从格伦·布鲁克谢尔的《计算机科学概论》中摘录的一段文字:“计算机的主存储器的一个小部分,CPU期望在其中找到初始程序,是由特殊的非易失性存储单元构成的。这种存储器被称为只读存储器(ROM)。”根据他的说法,主存储器由RAM和ROM两部分组成。我只想知道所谓的引导加载程序是否安装在主存储器的ROM部分上... @Sergey - xczzhh
@xczzhh - 是的,BIOS存储在只读存储器中,它会检测分区中存在的引导加载程序。安装任何操作系统后,它会在BIOS中创建一个类似标志的条目,以便检测相应的引导加载程序。 - atenz
1@xczzhh,不,引导加载程序位于硬盘或其他磁盘上。它与操作系统一起安装。除非您从主板制造商那里下载并安装更新,否则ROM永远不会改变。 - psusi
EFI使用EFI应用程序。它在NVRAM中加载EFI应用程序。 - Suici Doga
@SuiciDoga,不,EFI应用程序(基本上仅限于一些固件升级工具和引导加载程序)存储在硬盘的EFI系统分区中。NVRAM是EFI存储一些配置变量的地方,例如启动顺序。 - psusi
假设在我的电脑上我安装了另一个操作系统(与原始系统并存)。当我打开电脑时,BIOS从ROM中加载,BIOS加载位于第一个磁盘扇区的主引导记录(Master-Boot-Record),主引导记录加载GRUB,GRUB包含一个配置文件,指定操作系统的存储位置。1)由于我安装了新的操作系统,GRUB现在是否包含修改后的配置文件?2)如果我想使用其他引导加载程序而不是GRUB怎么办?3)如果在安装新的操作系统期间完全搞乱了GRUB的配置文件,我将无法加载任何操作系统,该如何修复? - mercury0114

ROM不在主内存中:

ROM不是主内存的一部分。它是一个独立的芯片,大多数情况下内置在更大的集成电路中。举个例子,你的个人电脑可能包含几个ROM。这些ROM内置在你的主板上。

一般来说:

  • ROM的存储容量非常小。这些存储器是非易失性的,也就是说,存储在ROM中的程序在断电后不会被擦除。
  • ROM用于存储永久性的程序,这些程序对于硬件的正确运行非常重要。
  • 典型的ROM示例是BIOS芯片。其中存储了非常低级别的引导和初始化硬件的程序。
你提到过,你读到了一篇文章,作者说:“ROM是主存储器的一部分”。这很令人困惑,因为通常主存储器指的是易失性的内存,比如RAM。但是,如果你将“主存储器”这个术语用于PC的整个内存空间,那么ROM就是该内存空间的一部分。需要注意的是,通常情况下,主存储器不包括ROM等类型的内存。 引导加载程序存储在哪里: 现代系统使用两阶段引导加载。第一步是从硬盘的一个扇区(通常称为引导扇区)加载一个小程序。这个小程序再从磁盘的某个位置加载一个被称为引导加载程序的程序。最后,引导加载程序加载操作系统。
对于Ubuntu系统来说,该过程如下:
在打开计算机后,存储在只读存储器(ROM)中的BIOS会自动运行并初始化PC硬件的各个部分。然后,它会检查定义的第一个引导设备(通常是硬盘)中的特定扇区。这个扇区是引导扇区,大小为512字节。
引导扇区中的程序被加载到内存中(第一阶段)。这个小程序包含了应该加载到内存中的下一个程序的信息,以及该程序在磁盘或引导设备中的位置。它加载了那个程序。在Ubuntu中,它是/boot/grub/core.img。
在第二阶段,操作系统加载程序GRUB通过将内核和初始RAM磁盘加载到内存中,并将控制权交给内核来加载所有必要的程序,如显示管理器、图形用户界面等。
所以,我们可以明确地说,引导加载程序既不存储在只读存储器(ROM)中,也不存储在随机访问存储器(RAM)中,它实际上存储在硬盘上(或其他启动设备,如可启动的光盘、USB 驱动器等),准确来说是硬盘的第一个扇区,大小为 512 字节,通常称为“引导扇区”。这个引导加载程序会加载操作系统加载器(在 Ubuntu 中是 grub),它也驻留在硬盘上(即 /boot/grub/ 文件夹),其任务是加载操作系统(比如 Ubuntu)。
作为测试,请移除硬盘(和所有其他启动设备)并尝试引导。您可以执行到 BIOS 步骤,但在那之后,您将无法引导任何东西。很可能 BIOS 会显示“找不到引导设备”或“找不到操作系统”或类似的消息。
希望这个答案能帮到您。
如需更多信息,您可以访问以下链接:
  1. http://en.wikipedia.org/wiki/Read-only_memory
  2. http://en.wikipedia.org/wiki/Random-access_memory

2ROM在过去的十年里一直没有比RAM更快。事实上,现代BIOS的首要任务之一就是将自身复制到RAM中,因为RAM速度更快。 - David Schwartz
1@DavidSchwartz,这已经过去十多年了。在90年代中期我使用的每台PC BIOS都有一个选项,可以将BIOS在RAM中进行缓存以提高速度。 - psusi
@Anwar,主内存的链接已失效。 - The Matt

一个兼容x86的处理器始终以所谓的“实模式”启动,这是一种16位模式,可用于寻址1兆字节的内存。从该地址空间中,有640K可供程序使用,而超过该范围的地址则被映射到不同的设备。
例如,从0xA000:0x0000开始的地址被映射到视频RAM,因此,在那里写入数据实际上是将数据写入视频适配器的内存,从而在屏幕上显示像素。
类似地,BIOS ROM从0xF000:0000开始,因此当CPU上电时,它会从预定义的地址开始逐个执行指令。BIOS ROM包含了初始程序,该程序通过执行“自检”或POST来启动。来自维基百科的描述:
BIOS软件内置于个人电脑中,是电脑在开机时首先运行的代码(“引导固件”)。当电脑启动时,BIOS的第一个任务是进行自检,初始化和识别系统设备,如CPU、RAM、视频显示卡、键盘和鼠标、硬盘驱动器、光盘驱动器和其他硬件。然后,BIOS会定位外围设备上保存的引导加载程序软件(被指定为“引导设备”),如硬盘或CD/DVD,并加载并执行该软件,将控制权交给它。这个过程被称为引导,或者开机启动,简称引导启动。
BIOS固件负责将磁盘的第一个扇区读入内存,并将控制权传递给一个小程序,该程序同样位于特定地址上。然后,MBR引导加载程序可以直接开始加载操作系统(就像MS-DOS的情况一样),或者加载“第二阶段”,这不仅限于单个磁盘扇区的范围。
引导加载程序使用多阶段方法的情况下,可以非常复杂,具有文本或图形界面,允许用户选择从哪个磁盘或分区加载操作系统。
所以,如果像Uri建议的那样,你想知道Windows引导加载程序和GRUB是否可以共存,答案是:实际的MBR只能包含一个第一阶段引导加载程序(来吧,整个扇区只有512字节),但是引导加载程序的第二阶段可能能够从不同分区“链式加载”操作系统。Windows引导加载程序只能识别和加载Windows,而GRUB能够加载Linux或将控制权传递给存储在其中一个分区的卷引导记录中的另一个引导加载程序,从而可以启动Windows或其他操作系统。后者的过程称为链式加载。
当你在已经安装了Windows的计算机上安装Ubuntu时,GRUB将被安装到MBR中,你将能够启动Ubuntu和Windows。
然而,如果在Ubuntu之后安装了Windows,GRUB将被Windows引导加载程序替换,你需要重新安装GRUB才能再次启动Ubuntu。

我猜他想知道Windows引导程序和GRUB是否可以共存。UEFI,GPT磁盘不使用MBR,这对它们有什么影响? - Uri Herrera
BIOS ROM位于 F000: 段,就在 1 MB 以下。640k 来自 A000: 以下的段,供实模式操作系统和程序使用。 - psusi
@psusi:你说得对,我重新表达了那部分内容。 - Sergey
谢谢你的回答。你的意思是启动操作系统需要多个引导加载程序(一个在BIOS中,另一个在MBR中)吗?这对我来说很新奇... :) - xczzhh
@xczzhh好的,BIOS中的代码不称为“引导加载程序”,存储在磁盘上的才是。我更新了我的回答以明确这一点。 - Sergey
严格来说,GRUB不能启动Windows。但它可以加载Windows引导程序,并将控制权交给它,然后Windows引导程序会像是系统上唯一的次级引导程序一样继续运行。 - Jon Hanna
@JonHanna:确实,我在句子中提到了链式加载,但表达不够清晰。我改进了段落。对于这个问题的所有答案都变得相当庞大 :) - Sergey

你所说的关于引导加载程序(bootloader)在ROM和MBR中的冲突可能是因为“引导加载程序”被用来指任何能够找出最小化加载代码以使计算机执行有用操作的代码,包括多阶段引导中的每个状态。
所以,起始状态是拥有一台计算机,它是一种可编程设备,但不知道如何加载软件运行,因为它没有加载任何软件。(因此,“引导”自己从“靴带”上拉起来)。
从历史上看,这个问题有几种不同的解决方案,但现在我们从ROM中开始加载一些代码(很可能是严格的EEPROM),这足以让它查看不同的设备并依次尝试它们,直到找到一个可引导的设备。
这就是为什么许多系统会在你放入操作系统安装盘时从CD或DVD启动,否则从硬盘启动。BIOS(ROM上的代码,包括我们正在谈论的代码和其他一些低级别的启动代码)被设置为首先查看CD/DVD驱动器,然后如果找不到任何内容,则查看硬盘。调整者通常将其设置为忽略CD/DVD驱动器,除非手动请求,以免浪费时间旋转一个无法引导的磁盘。

这个ROM中的代码有时被称为"引导加载程序"。

当它知道要查看哪个驱动器时,它会查看MBR,其中包含关于主分区的信息 - 如果你甚至不知道磁盘的哪个部分是哪个分区,更不用说每个分区如何挂载了 - 以及一些带有进一步指令的代码。(顺便说一下,这就解释了为什么某些操作系统 - 如Windows - 只能安装在主分区上,这些分区的详细信息都在MBR中,而且它们的引导加载程序只读取了MBR中的分区信息,它不加载EBR来了解逻辑分区,就像它根本不存在一样)。

那段可执行代码也被称为引导加载程序。当我们需要区分它和接下来的内容时,它被称为主引导加载程序(因为除非我们自己制作BIOS,否则我们无法控制ROM部分)。
由于只有大约400字节的空间,这段代码将非常小,所以要实现任何实际功能,它会加载一些更大的代码,因为它不必受到这个限制的影响。
这段代码也被称为引导加载程序。当我们需要区分它和之前的内容时,它被称为次级引导加载程序。
如果你只有一个操作系统,或者你系统上的所有操作系统都使用兼容的引导加载程序(例如两个都使用GRUB的Linux安装),那么这段代码可能是最后阶段。它可以显示菜单(如果需要),加载内核,并将控制权交给操作系统。
在你的操作系统与引导加载程序不兼容的情况下,它可以进行链式加载。例如,如果你的机器上同时安装了Windows和Linux,GRUB选项加载Windows实际上会加载另一个仅知道Windows安装的引导加载程序,并将控制权交给它。虽然这是过程中的第三阶段,但它仍被称为“次级引导加载程序”,因为它既不知道也不关心之前运行的其他次级引导加载程序。对于使用不同类型的次级引导加载程序的Linux安装,情况也是如此。
当我们谈论Linux的“引导加载程序”时,通常并不是指ROM代码(它不是Linux的一部分,也不会因为安装Linux而改变)。当我们执行“update-grub”命令时,我们正在更改次级引导加载程序,它通常位于特定安装的/boot目录中。当我们执行“install-grub”命令时,我们不仅更改次级引导加载程序,还更改MBR中的主引导加载程序,以便它具有足够的代码来知道/boot的位置(可能在执行过程中启动软件RAID),并在自身执行时加载和执行/boot。
所以,总结一下,当你说ROM是主存储器的一部分时是错误的,因为它是独立的。(事实上,RAM被视为ROM的反义词)。你在说引导加载程序(bootloader)和MBR时是正确的,因为它们是整个过程中的两个步骤,并且有时都被称为这个名字。关于“不同的操作系统是否将其引导加载程序存储在不同的位置?”的答案是“大多数情况下是”,因为如果你安装了不兼容的次级引导加载程序,它们要么会隐藏其他引导加载程序(如果你先安装了Linux再安装Windows),要么在请求时链入其他引导加载程序(如果你解决了这种情况,或者在Windows之后安装了Linux)。但是,如果两个操作系统兼容,它们可以共享一个次级引导加载程序(例如,如果你在已经安装了相同类型的次级引导加载程序的Linux之后再安装另一个Linux,并且它能看到另一个Linux [有时候软件RAID会让事情变得复杂,并需要链入加载])。
在以ROM和RAM编程的日子里,情况就不同了。例如,在ZX Spectrum上,ROM是16kiB,并包含一个BASIC解释器,因此除了为将某些内容加载到其48kiB或128KiB(分页)RAM中提供起始点之外,还有一整套BASIC解释器的功能可供RAM中的程序使用(为什么要编写三角函数,当计算机已经在已知位置上有一个?尤其是当你只有48kiB的代码运行空间时)。这个ROM也以与RAM相同的方式可见,只是地址不同。在这种情况下,ROM与RAM一样是主存的一部分,但不可写入。如今,一旦完成引导的第一阶段,你基本上会忽略ROM。

从前,引导程序存储在类似于电报机或打孔卡片介质上的打孔纸带上(现在已经很少见了)。这个过程以前被称为IPL,即初始程序加载。有时候如果没有可用的纸带或卡片阅读器,就需要通过前面板上的控制台直接将二进制IPL代码输入处理器中。真是费劲啊!
现如今,IPL代码存储在pROMs中,当执行时会加载和执行任何定制的次级引导加载程序,以加载(启动)所需的操作系统。次级加载程序可以位于任何由IPL代码知道或可寻址的设置的任何介质上。

制作一个最小工作示例,并在模拟器上运行它以理解这些概念。
printf '\364%509s\125\252' > main.img
qemu-system-x86_64 -hda main.img

这是一个非常简单的"引导加载程序",只执行一条hlt指令。更多信息请访问:https://stackoverflow.com/a/32483545/895245

您可以使用以下命令在真实硬件上运行它:

sudo dd if=main.img of=/dev/sdX

插上USB并将其连接到计算机,然后从中启动。
当你这样做时,很明显引导加载程序是存在于永久存储介质如USB或硬盘上的东西。
存储在只读存储器(ROM)中的是启动引导加载程序的代码,被称为固件(或不太准确地说是BIOS)。

引导加载程序通常位于硬盘的第一个扇区,通常称为主引导记录。
祝好!