Linux系统启动

本文主要介绍了Linux系统启动流程相关内容

一、概览

开机实际上是一件很复杂的事情,该动作的主要目的就是让冷冰冰的机器帮助我们完成需要的工作。本文所介绍的,只是Linux系统的大致启动过程

需要说明的是,近年来从底层的BIOS到上层的init程序都有了一些变化,而系统启动的大致原理依旧,本章节先以“BIOS”来表示Legacy BIOS与UEFI,以GRUB表示引导程序,以INIT来表示各init程序……,大致说明系统启动过程,后面的章节将分别介绍之

Linux启动大致过程如下

BIOS
Boot Loader
Kernel
INIT

我们知道,计算机只有在CPU加载到指令后才能根据指令完成工作,而其加载的指令存在于RAM(Random Access Memory,随机访问存储器),即我们当前用作内存的介质,而该设备断点后将无法保存数据,那么此时指令从何而来?

Linux系统初识-计算机体系结构中有介绍过,我们需要外部存储设备来帮助持久保存数据。该设备即外存或辅储,一般使用HDD或SSD为介质

而这就需要在开机时将外存中的指令读取到内存,而后加载到CPU,而这个动作本身,也是需要指令来完成的!这该如何进行?

这就需要计算机有“自举”能力,现代计算机的设计中,在我们按下电源键后,主板将会把一段存储在特殊存储器上的代码传入CPU中,注意,该动作使用硬件逻辑完成的,不需要指令的参与,就像我们打开电灯开关,灯就会亮一样

这段代码我们将其称之为BIOS(Basic Input/Output System,基本输入输出系统),他主要负责探测硬件(POST(Power On Self Test,加电自检))、选择启动设备

当上述操作无误后,BIOS将选择的设备中的代码载入CPU,即Boot Loader,用于引导分区上的操作系统,在此处由于分区表类型不同稍有差异

对于完全支持UEFI引导:
UEFI
Boot Loader
Kernel
INIT
对于BIOS引导:
BIOS
Boot Loader
Grub
Kernel
INIT

由于BIOS本身不能识别文件系统,故要使用其他机制辅助,事实上,上图对于BIOS的引导中,Boot Loader代码也属于Grub程序,而使用UEFI的引导中,Boot Loader即Grub,不同之处下文将详细介绍,为了方便叙述,本文的章节划分按照上图BIOS引导的架构

而后通过Grub实现从当前物理存储设备选择所启动的操作系统,以及内核所在位置与相关启动特性

上述操作完成后,根据Grub中指定的内核与相关参数启动Kernel,在Kernel中启动用户空间的第一个进程,即init程序,至此,系统启动完成

事实上init程序启动后,还会有一些相关配置,此处没有列出,下文将详细介绍

二、BIOS

该过程是计算机加电之后运行的第一段程序,如今,UEFI即将全面取代BIOS,通常,我们将该程序称为固件(Firmware),负责硬件检测,以及为操作系统提供运行时服务

1. BIOS

BIOS(Basic Input/Output System,基本输入输出系统)固件安装在PC的主板(Motherboard)上的独立存储器中,早期位于ROM(Read Only Memory,只读存储器)中,不可更改,后来位于闪存(Flash Memory)中(常为EEPROM),带来的好处是可以在不从主板上移除芯片的情况下重写它,这允许对BIOS固件进行简单的最终用户更新,从而可以添加新功能或修复错误

通常,我们也将存储BIOS的储存器称为BIOS芯片

主要功能

  1. BIOS中断服务程序实质上是软件与硬件之间的一个可编程接口,主要用于程序软件功能与硬件之间连接。例如,系统对光驱、硬盘等管理,中断的设置等

  2. BIOS系统设置程序:BIOS提供一个“系统设置程序”,主要来设置系统底层的各项参数,如系统的基本情况、CPU特性、软硬盘驱动器等部件的信息,该程序在开机时按某个键就可进入设置状态

  3. POST:接通电源后,系统首先由POST(Power On Self Test,加电自检)程序来对内部各个设备进行检查。通常完整的POST自检将包括对CPU、640K基本内存、1M以上的扩展内存、ROM、等进行测试,一旦在自检中发现问题,系统将给出提示信息或鸣笛警告,其测试流程如下1

    引导系统重置REST引导CPU。
    CPU指向BIOS自我测试的地址FFFFOH并打开CPU运行第一个指令。
    CPU内部寄存器的测试。
    CMOS 146818 SRAM检查。
    ROM BIOS检查码测试。
    8254计时/计数器测试。
    8237 DMA控制器测试。
    74612页寄存器测试。
    REFRESH刷新电路测试。
    8042键盘控制器测试。
    DRAM 64KB基本存储器测试。
    CPU保护模式的测试。
    8259中断控制器的测试。
    CMOS 146818电力及检查码检查。
    DRAM IMB以上存储器检查。
    显卡测试。
    NMI强制中断测试。
    8254计时/计数器声音电路测试。
    8254计时/计数器计时测试。
    CPU保护模式SHUT DOWN测试。
    CPU回至实模式(REAL MODE)。
    键盘鼠标测试。
    8042键盘控制器测试。
    8259中断控制器IRQ0至IRQ18建立。
    磁盘驱动器及界面测试。
    设置并行打印机及串列RS232的界面。
    检查CMOS IC时间、日期。
    检查完成

  1. BIOS系统启动自举程序:系统完成POST自检后,BIOS就首先按照系统CMOS设置中保存的启动顺序搜索软硬盘驱动器及CD-ROM,网络服务器等有效地启动驱动器,读入操作系统引导记录,然后将系统控制权交给引导记录,并由引导记录来完成系统的顺序启动

CMOS与BIOS

很多人对二者傻傻分不清,这里说明一下

BIOS是一段程序,存位于EEPROM(Electrically-Erasable Programmable Read-Only Memory,电可擦除可编程只读存储器),是一种可以通过电子方式多次复写的半导体存储设备,可以用特定的电压,来抹除芯片上的信息,以便写入新的数据(注意,早期的BIOS并非如此,上文有介绍)

而BIOS设置的配置记录放在CMOS(Complementary Metal Oxide Semiconductor,互补金属氧化物半导体)芯片中,该芯片属于RAM,断点后数据将丢失

故主板上有一块电池,为该存储器供电,若取出电池,则可重置这些信息,如BIOS密码、启动次序、时间等

Boot Sequence

在BIOS提供的配置页面中,提供了让用户选择启动次序(Boot Sequence)的接口,如下图

Boot_Sequence

上图为VMware Workstation 15的BIOS界面,实际界面样式因不同主板或BIOS程序而异,然意义相同

配置启动设备后,BIOS工作完成后将根据这里配置的顺序从对应设备中寻找启动代码,即查看该设备首512字节是否是以0x55 0xAA结尾,若不是,则认为该设备无启动能力,继续寻找下一个设备,否则加载该代码,控制权移交至该代码,BIOS工作完成

可参看Linux存储管理相关内容

2. UEFI

UEFI(Unified Extensible Firmware Interface,统一可扩展固件接口)是一种个人计算机系统规格,用来定义操作系统与系统固件之间的软件界面,作为BIOS的替代方案

概述

UEFI的前身是Intel在1998年开始开发的Intel Boot Initiative,后来被重命名为可扩展固件接口(Extensible Firmware Interface,缩写EFI)。Intel在2005年将其交由统一可扩展固件接口论坛(Unified EFI Forum)来推广与发展,为了凸显这一点,EFI也更名为UEFI(Unified EFI)。UEFI论坛的创始者是11家知名计算机公司,包括Intel、IBM等硬件厂商,软件厂商Microsoft,及BIOS厂商AMI(英语:American Megatrends)、Insyde及Phoenix

目前的最新版本为UEFI-2.7A2

UEFI在概念上非常类似于一个小型的操作系统,并且具有操控所有硬件资源的能力,而其一些特性与操作系统有着本质区别

  • 它只是硬件和预启动软件间的接口规范

  • UEFI环境下不提供中断的机制,也就是说每个EFI驱动程序必须用轮询(polling)的方式来检查硬件状态,并且需要以解释的方式运行,较操作系统下的机械码驱动效率更低

  • UEFI系统不提供复杂的缓存器保护功能,它只具备简单的缓存器管理机制,具体来说就是指运行在x64或x86处理器的64位模式或保护模式下,以最大寻址能力为限把缓存器分为一个平坦的段(Segment),所有的程序都有权限访问任何一段位置,并不提供真实的保护服务

UEFI

UEFI的组成

x64计算机平台的UEFI通常包含以下几个部分:3

  • Pre-EFI初始化模块
  • EFI驱动程序执行环境(DXE)
  • EFI驱动程序
  • 兼容性支持模块(CSM)
  • EFI应用程序
  • GUID磁盘分区表

在实现中,统一可扩展固件接口(UEFI)初始化模块和驱动执行环境通常被集成在一个只读存储器中(多为NVRAM

Pre-EFI初始化程序在系统开机的时候最先得到执行,完成存储器的初始化工作,然后加载UEFI DXE(驱动程序执行环境)

当DXE被加载运行时,系统便具有了枚举并加载其他UEFI驱动程序的能力。在基于PCI Express架构的x64计算机系统中,系统会加载UEFI内置的驱动程序模块,完成UEFI固件、CPU、存储器、芯片组及主板的进一步初始化,然后初始化各PCIe控制器、PCIe适配器(如RAID扩展卡或显卡)及芯片组内置PCIe适配器(如芯片组内置的SATA、USB、网卡等功能)并加载这些PCIe设备的UEFI驱动程序(如果有的话,也有可能是加载PCIe设备的Legacy Option ROM)

UEFI驱动程序不仅可以包含在PCIe适配器的ROM中(作为PCIe设备的UEFI Option ROM),还可以以.EFI文件的形式被方便的加载

在UEFI规范中,一种突破传统MBR磁盘分区结构限制的GUID磁盘分区系统(GPT)被引入,新结构中,磁盘的主分区数不再受限制(在MBR结构下,只能存在4个主分区),另外UEFI+GPT磁盘分割表结合还可以支持2.1 TB以上硬盘,并且分区类型将由GUID来表示

GPT磁盘分区表的硬盘可包含EFI系统分区(ESP),EFI系统分区(ESP)可以被UEFI固件访问,可用于存放操作系统的引导程序、EFI应用程序(如OEM的备份程序和硬件诊断程序)等等

EFI系统分区采用FAT文件系统,在Windows操作系统下默认在“本机”中隐藏。UEFI固件通过运行EFI系统分区中的引导程序文件(扩展名为.EFI的UEFI应用程序)引导操作系统。CSM是在x86平台UEFI系统中的一个特殊的模块,它将为不具备UEFI引导能力的操作系统以及16位的传统Option ROM(即非EFI的Option ROM)提供类似于传统BIOS的系统服务

Secure Boot功能要求原生UEFI(即关闭CSM),因此在UEFI固件设置中打开CSM前,需要在UEFI固件设置中关闭Secure Boot

下图为

UEFI

引导

UEFI启动

与BIOS不同,UEFI不依赖于引导扇区,而是将引导管理器定义为UEFI规范的一部分。当计算机启动时,启动管理器会检查启动配置并根据其设置加载到内存中,然后执行指定的OS加载程序或操作系统内核。引导配置由存储在NVRAM中的变量定义,包括指示OS加载器和OS内核的文件系统路径的变量

UEFI可以自动检测OS加载程序,从而可以从USB闪存驱动器等可移动设备轻松启动。这种自动检测依赖于到OS加载器的标准化文件路径,路径根据计算机体系结构而变化

从GPT分区磁盘引导UEFI系统通常称为UEFI-GPT引导。尽管UEFI规范要求完全支持MBR分区表[28],但某些UEFI固件实现会立即切换到基于BIOS的CSM引导,具体取决于引导磁盘分区表的类型,从而有效防止UEFI引导从MBR分区磁盘上的EFI系统分区。这样的引导方案通常被称为UEFI-MBR

引导管理器通常具有文本用户界面,因此用户可以从可用引导选项列表中选择所需的OS(或系统实用程序)

CSM启动

为了确保向后兼容性,PC级机器上的大多数UEFI固件实现还支持从MBR分区磁盘通过传统BIOS模式启动,通过提供传统BIOS兼容性的兼容性支持模块(CSM)。在这种情况下,通过忽略分区表并依赖引导扇区的内容,以与基于BIOS的传统系统相同的方式执行引导

从MBR分区磁盘启动BIOS样式通常称为BIOS-MBR,无论是在UEFI还是基于BIOS的传统系统上执行。此外,还可以从GPT磁盘启动传统的基于BIOS的系统,并且这种启动方案通常称为BIOS-GPT

在兼容性支持模块允许传统的操作系统和一些选项ROM仍然使用不支持UEFI。它还提供了所需的传统系统管理模式(SMM)功能,称为CompatibilitySmm,作为UEFI SMM提供的功能的补充。这是可选的,高度芯片组和平台特定。这种传统SMM功能的一个示例是通过模拟其经典的PS / 2对应物,为键盘和鼠标提供USB传统支持

该方案作为目前UEFI与BIOS的过度阶段的缓冲,英特尔宣布计划到2020年逐步停止对CSM的支持

UEFI与BIOS在启动过程上的区别

UEFI启动过程

UEFI_Boot

对应到UEFI个模块为,如下图。事实上,左半部分中,SEC,PEI,DXE称之为PI(Platform Initialization)规范,UEFI纯粹地是一个接口规范,它不会具体涉及平台固件是如何实现的。“如何实现”这一内容是PI要解决的问题

BDS,TSL,和RT一起,属于UEFI规范

UEFI_Boot

SEC阶段
SEC阶段内存尚未被初始化,故UEFI将CPU缓存作为内存使用,即Cache As RAM
PEI阶段
和BIOS的初始化阶段类似,PEI阶段用以唤醒CPU及内存初始化。PEI用SEC设置好的Cache As RAM,执行一些PEIM(初始化模块),用于初始化一些硬件
DXE阶段:
DXE的主要功能在加载驱动。此阶段所有的内存、CPU、PCI、USB、SATA和Shell等都会被初始化
BDS阶段:
在BDS(引导设备选择)阶段,它负责执行所有符合UEFI驱动模型(UEFI driver model)的驱动。这是一个发现并一个个连接的过程,一个个启动设备被发现,其设备路径(device path)也被连接起来。在万事俱备后,一个界面被显示出来(嵌入式系统上可以没有),供用户进行设置和选择启动设备,这就是大家熟悉的BIOS界面,用户可以自开机管理者程序页,选择要从哪个侦测到的开机设备来启动
TSL阶段:
然后进入TSL(短暂系统载入)阶段,由操作系统接手开机。除此之外,也可以在BDS阶段选择UEFI Shell,让系统进入命令列,进行基本诊断和维护

BIOS启动过程

BIOS启动过程较为简单,一下做大致介绍

  1. 初始化

    系统加电,CPU会自行重置为初始状态。BIOS boot block初始化阶段启动,此时内存尚未初始化,没有内容可以执行,所以厂商让CPU去寻找系统BIOS ROM中的reset vector(重置向量) :用一个固定的位置来启动所谓的BIOS boot program

    一般来说程序会在内存的FFFF0h处,也就是在UMA(上层记忆区域)靠结尾的地方。为避免ROM大小改变造成兼容问题,所以一般会选择放这里。它的内容只有一个jump指令,进一步跳到真正的BIOS启动程序

    各家IBV (independent BIOS vender;独立BIOS供应商)可以放在不同的位置,只要通过jump来指定即可

    在该阶段,系统的CPU、芯片组、Super I/O和USB只有部分初始化,仅获取足够信息来应付万一BIOS开机失败,可以利用其他储存设备来救援BIOS的boot block

  2. POST

    然后BIOS开始施行POST,它通常被放在内存C0000h处,作用是显卡的初始化,而大部分的显示卡都会在显示器上显示其相关讯息。这就是为何各位在开机的时候,首先会在显示器的画面左上角出现有关显示卡讯息的原因。

    下一步BIOS会显示启动画面,并开始更深入的检测,如果这时候遇到任何错误,就会在画面上显示错误消息

  3. 记录系统的配置

    此时BIOS会对系统进行进一步的确认,看看你的电脑究竟安装了那些系统资源或设备。有些电脑会逐步显示这些被侦测到的设备,例如BIOS支持随插即用,那它将会侦测和配置随插即用装置,并显示由BIOS侦测到的随插即用设备

    在这些检测结束后,BIOS会打出一个总结表于画面上。而这个总结表在部分IBV的设定中是可以让使用者开启或关闭的。当然也有些IBV为加速开机把这一步直接隐藏省略

  4. 提供常驻程序
    提供操作系统或应用程序调用的中断向量,如INT 10h(VGA图形及文字输出中断)等
  5. 加载系统
    到这里是系统检测的部分,接下来BIOS便开始寻找引导设备,用户可以通过在BIOS的设定来决定搜寻顺序

总结

此处将UEFI与BIOS的引导方式总结如下

BIOS

BIOS只认识设备,不认识分区、不认识文件

启动过程:根据CMOS中保存的顺序,查看存储设备,其前512字节是不是以0x55 0xAA结尾?若是则执行这段代码,完成

UEFI

UEFI认识设备,还认识设备ROM,还认识分区表、认识文件系统以及文件

启动过程:经过一系列初始化后,按照设置里的顺序寻找启动项,一般有两种类型

  • 文件启动项,大约记录的是某个磁盘的某个分区的某个路径下的某个文件。对于文件启动项,固件会直接加载这个EFI文件,并执行
  • 设备启动项,大约记录的就是“某个U盘”、“某个硬盘”。(此处只讨论U盘、硬盘)对于设备启动项,UEFI标准规定了默认的路径“\EFI\Boot\bootX64.efi”。UEFI会加载磁盘上的这个文件。文件不存在则失败

UEFI-2以后,新增了SecureBoot功能。开了SecureBoot之后,主板会验证即将加载的efi文件的签名,如果开发者不是受信任的开发者,就会拒绝加载

三、Boot Loader

事实上在UEFI+GPT的引导方式下无需该步骤,从上文可看出,若使用该方式引导,由于UEFI可直接识别文件系统,在BDS阶段选择操作系统后即可进入下一步

本章主要介绍没有使用GPT分区表或GPT分区表不被识别的情况,如

  • BISO+MBR
  • UEFI+MBR
  • BIOS+GPT

此处纠正一个问题,很多人认为BIOS+GPT无法引导,其实是可以的,上文已有介绍,GPT分区中LBA0位MBR兼容区。只是由于微软在默认情况下不允许Windows操作系统通过BIOS引导GPT分区而已

然而我们也可以经过配置是的Windows在BIOS+GPT方式下启动,chainloader指定ESP中的bootmgfw.efi即可

故对于BIOS与UEFI、BMR与GPT,其各种组合都是可以引导的,即

  • BISO+MBR
  • UEFI+MBR
  • BIOS+GPT
  • UEFI+GPT

若使用UEFI+MBR,则需要使用CSM,即打开兼容性支持模块,如此,UEFI将会读取MBR中的代码,这段过程与BIOS+MBR基本无异

当BIOS(或使用SCM的UEFI)选择到指定的启动设备后,由于它不能识别文件系统,故将读取选择设备的首部446字节,这是一段代码,即Boot Loader(引导加载器),由于代码较为简短,无法执行复杂功能,故其主要用于将执行流执行另一部分

前面已经提及,Boot Loader为Grub的一部分(第一部分),而上面指向的另一部分即Grub的第二部分

可参考Linux存储管理-MBR相关内容

四、GRUB

1. Boot Loader

严格来讲,该章节应该交Boot Loader,而由于上一章MBR中占用,且如今Grub为最著名的Boot Loader程序,此处将其命名为GRUB

这里对Boot Loader程序做简要说明,该程序用于接管BIOS/UEFI交过来的控制系统权,用于加载系统内核

对于Windows,该程序为ntloader,nt即New Technology,而Windows中更新的Boot Loader程序为Windows Boot Manager

对于Linux平台,有两种较为常见

  • LILO,即LInux,LOader,Linux加载器,不能引导1024柱面(Cylinder)以后分区上的内核,故不支持大硬盘,常用于嵌入式平台

  • GRUB,即GRand Unified Bootloader

    • Grub 0.x:Grub Legacy
    • Grub 2

2. Grub概述

事实上,我们所谓的Grub应该被称为GNU Grub(就像我们每次说的Linux,Stallman先生都会强调:应该是GNU Linux!)

Grub 2引入了一些更为有效的能力:

  • 支持多种文件系统,如ext4、xfs、ntfs等

  • Grub 2可以访问已经安装的设备上的数据,可以直接从LAM和RAID中读取数据

  • Grub 2使用了模块机制,引入很多模块,通过动态加载模块来扩展功能,这样允许core镜像足够小。

  • 支持自动解压

  • 支持脚本语言,包括简单的语法,如条件判断,循环,变量和函数

  • 国际化语音,包括支持非ASCII的字符集和类似gettext的消息分类,字体,图形控制台等

  • 支持rescue模式,可用于系统无法引导的情况

  • Grub 2有更可靠的方法在磁盘上有多个文件系统时发现文件和目标内核,可以用命令发现系统设备编号或者是UUID

  • 有一个灵活的命令接口。如果没有配置文件的存在,grub2会自动进入命令模式

传统Grub在运行时由三个阶段

  • Stage 1:位于MBR,用于引导Stage 2
  • Stage 1_5:位于MBR之后的扇区,为识别内核文件所在的文件系统提供文件系统识别扩展
  • Stage 2:位于/boot分区,主要的引导工作在此完成

其中Stage 1_5非必要

3. Grub的安装位置

这里需要说明的文件为

  • Boot.img:Stage 1对应的文件,MBR分区格式的磁盘中,放在MBR里; GPT分区格式的磁盘中,放在Protective MBR中

  • Core.img:Stage 1_5对应的文件,32256字节大小。MBR分区格式的磁盘中,放在紧邻MBR的若干扇区中;GPT分区格式的磁盘中,则放在34号扇区开始的位置(第一个分区所处的位置),而对应的GPT分区表中的第一个分区的entry被置空

  • /boot/grub:步骤2对应的文件目录,放在系统分区或者单独的Boot分区中

Grub程序各部分安装的位置如图
  • MBR分区表:
    Grub_MBR
  • GPT分区表
    GRUB_GPT

4. 启动Kernel前的准备

在Grub加载Kernel后,Kernel将启动init程序,以下为./linux.init/main.c部分代码:

static int __ref kernel_init(void *unused)
{
	kernel_init_freeable();
	/* need to finish all async __init code before freeing the memory */
	async_synchronize_full();
	free_initmem();
	mark_rodata_ro();
	system_state = SYSTEM_RUNNING;
	numa_default_policy();

	flush_delayed_fput();

	if (ramdisk_execute_command) {
		if (!run_init_process(ramdisk_execute_command))
			return 0;
		pr_err("Failed to execute %s\n", ramdisk_execute_command);
	}

	/*
	 * We try each of these until one succeeds.
	 *
	 * The Bourne shell can be used instead of init if we are
	 * trying to recover a really broken machine.
	 */
	if (execute_command) {
		if (!run_init_process(execute_command))
			return 0;
		pr_err("Failed to execute %s.  Attempting defaults...\n",
			execute_command);
	}
	if (!run_init_process("/sbin/init") ||
	    !run_init_process("/etc/init") ||
	    !run_init_process("/bin/init") ||
	    !run_init_process("/bin/sh"))
		return 0;

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

内核会从三出搜索该程序,若依然没有找到,则启动一个shell,这些程序位于/(根)下,故而此时Kernel需要有加载根文件系统的能力,而/的文件系统与/boot可以位于不同分区,加之Kernel中不可能将所有文件系统的驱动都包含,而此时需要如何访问/

我们知道,Boot Loader程序有时需要借助Stage 1_5阶段来加载/boot所在分区的相应驱动

同样的,将相关文件系统的驱动做成一个特定文件,在Kernel访问/之前,先加载该文件即可

显然,该文件需要内核能直接访问,故其在/boot中,在CentOS 5中,该文件为ramdisk,对应文件名一般为initrd,而在CentOS 6之后,该文件为ramfs,对应文件名一般为initramfs

从名称上可以看出,CentOS 5中通过将RAM模拟为块设备,而Linux的缓存机制导致将可能再次在RAM中缓存该内容,造成不必要的浪费,而ramfs本身就是一个tmpfs的内存盘,拥有最小化的设计,绕过了缓存机制,也消除了多余的内存占用

因此,Kernel与initrd(或initramfs)必须存储在Boot Loader程序可以访问的位置,并且需要将initrd(或initramfs)加载后传递其地址给Kernel,如此,内核即可访问根文件系统

5 .Grub Legacy

功能

  1. 提供菜单,选择要启动时的内核或系统;

    • 允许传递参数给内核
    • 可以隐藏选择界面
  2. 提供交互式接口

    • e:编辑模式,用于编辑菜单
    • c:命令模式,交互式接口
  3. 基于密码的保护

    • 启用内核映像,定义在相应的title
    • 传递参数,即进入编辑模式,定义在全局段中

配置文件

配置文件的读取主要在Stage 2完成,其配置文件为/etc/grub.conf,该文件指向/boot/grub/grub.conf,如下为RHEL 5中的一个实例,以之为例说明个字段意义

default=0  # 设定默认启动的title的编号,从0开始

timeout=5  # 等待用户选择的内核或OS超时时长,单位:秒

splashimage=(hd0,0)/grub/splash.xpm.gz
	# 指定grub的背景图片,gimp工具可以编辑图片,要保存为.xpm格式,然后使用gzip压缩(.gz)

hiddenmenu # 隐藏菜单

password redhat # grub的密码(明文),菜单编辑密码

password --md5 $1$HKXJ51$B9Z8A.X//XA.AtzU1.KuG.
	# grub加密密码,可以使用grub-md5-crypt命令来计算密码

title Red Hat Enterprise Linux Server (2.6.18-308.el5)
	# 内核标题,或操作系统名称,字符串,可自由修改
	root (hd0,0)
		# 内核文件所在的设备;对grub而言,所有类型硬盘一律hd,格式为
		(hd#,N);
		# hd#, #表示第几个磁盘;从0开始编号
		# N表示对应磁盘的分区;从0开始编号

	kernel /vmlinuz-2.6.18-308.el5 ro root=/dev/vol0/root rhgb quiet
		# 内核文件路径,及传递给内核的参数,参数即/proc/cmdline中的内容

		# 参数: ro root=/path/to/DEVICE
			# 将/path/to/DEVICE所代表的设备当做内核启动时的根,以只读方式挂载
			# quiet:静默模式, 内核初始化的信息不再输出

	initrd /initrd-2.6.18-308.el5.img
		# 文件:通常为cpio归档,并使用gzip压缩,通常以.img作为扩展名
		# ramdisk文件路径,即临时的根,是一个完整意义上的Linux
		# 注意:以上两项显示根下的文件是由于文件位于/boot/目录,该目录是单独的分区,而此时没有文件系统,遂grub直接访问该分区
		# 若/boot没有单独分区,则会正常显示

	password --md5 $1$HKXJ51$B9Z8A.X//XA.AtzU1.KuG. # 将该字段放置于所有title上面,为全局密码,放在某一title中,为内核启动密码
title Install Red Hat Enterprise Linux 5
	root (hd0,0)
	kernel /vmlinuz-5 ks=http://172.16.0.1/workstation.cfg ksdevice=eth0 noipv6
	initrd /initrd-5
	password --md5 $1$FSUEU/$uhUUc8USBK5QAXc.BfW4m.

命令行

help:获取帮助列表
	help KEYWORD:命令详细帮助
	
find:查找文件
	find (hd#,N)/PATH/TO/SOMEFILE
	设定根设备后可省略设备
	
root:设定根设备
	root (hd#,N)
	
kernel:指定本次启动使用的kernel
	kernel /PATH/TO/KERNEL_FILE
	
	额外可添加内核支持使用的cmdline参数
		init=/PATH/TO/INIT
		selinux=0
		root=/PATH/TO/ROOT
		…
	
initrd:为选定的内核提供额外文件的ramdisk
	initrd /PATH/TO/INITRAMFS_FILE
	该文件版本需要与kernel版本完全匹配
	
boot:引导启动选定的内核

安装grub

可使用grub-install命令安装grub,使用方式为

grub-install --root-directory=DIR /dev/DISK

还可以在grub交互界面安装:

grub> root (hd#,#)
grub> setup (hd#)
grub指定设备的方式
hd(#,#)
hd#: 磁盘编号,用数字表示;0开始编号
#: 分区编号,用数字表示; 0开始编号

手动在grub命令行接口启动系统

grub> root (hd#,#)
grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE
grub> initrd /initramfs-VERSION-RELEASE.img
grub> boot

6. Grub 2

Grub 2的软件包名即grub2,他与Grub Legacy的区别上文已有介绍

配置文件

  • /boot/grub2/grub.cfg:启动项配置,可由grub2-mkconfig生成

  • /etc/default/grubgrub2-mkconfig工具生成配置时的参考信息

  • /etc/grub.d/*:该目录下主要为一些脚本,分别配合对应grub.cfg上的各个部分

应用

查看当前默认启动项
grub2-editenv list
设置默认启动项
方式一:grub2-set-default
方式二:修改/etc/default/grub,修改GRUB_DEFAULT=##:该数字为grub菜单中各启动项的顺序),而后使用grub2-mkconfig -o /boot/grub2/grub.cfg生成配置文件
安装grub2
grub2-install [--root-directory=/PATH/TO/ROOT] [DEVICE]
	若为UEFI,则DEVICE可省略
生成新的grub.cfg文件
grub2-mkconfig -o /boot/grub2/grub.cfg

五、Kernel

Grub工作完成后,Kernel接管控制权,在此其主要工作为:

  1. 设备探测
  2. 驱动初始化(可能会从initrd(在redhat6中叫做initramfs)文件中装载驱动模块)
  3. 以只读方式挂载根文件系统(稍后init会重新挂载文件系统)
  4. 装载第一个进程init(PID: 1)

grub中指定的initrd(或initramfs)在此处将会用到,另外,第一个进程在CentOS 7中称为systemd,下一章将介绍

内核的实现中,我们介绍了当前操作系统内核实现的两种主流方式

  • 微内核将通过各内核子系统实现管理工作,如Windows,Solaris
  • 宏内核将各种功能集于一身,Linux内核就是这种设计方式

理论上讲,微内核的设计思想更为先进,而事实上要协调好各个子系统去实现复杂管理任务,这本身也是一个非常复杂的工作

Linux内核通过将个功能分为不同的模块,按需动态装卸载,这些模块在Kernel 2.6版本以后本称为Kernel Object,文件名后缀为.ko(之前为.o

BTW,在Linux中共享库为Shared Object(.so 共享对象,在Windows中为Dynamic Link Library(.dll 动态链接库

Linux内核文件一般位于/boot/vmlinuz-VERSION-RELEASE,而其模块文件为/lib/modules/VERSION-RELEASE/,而上文介绍的ramdisk,在CentOS 5中位于/boot/initrd-VERSION-RALEASE.img,而在CentOS 6之后的版本为/boot/initramfs-VERSION-RELEASE.img

[root@localhost ~]# ll /boot/vmlinuz-`uname -r` -h
-rwxr-xr-x. 1 root root 4.8M Mar  6  2015 /boot/vmlinuz-3.10.0-229.el7.x86_64
[root@localhost ~]# ll /lib/modules/`uname -r` -h
total 2.6M
lrwxrwxrwx.  1 root root   38 Dec 20 04:15 build -> /usr/src/kernels/3.10.0-229.el7.x86_64
drwxr-xr-x.  2 root root    6 Mar  6  2015 extra
drwxr-xr-x. 11 root root 4.0K Dec 20 04:15 kernel
-rw-r--r--.  1 root root 668K Dec 20 04:22 modules.alias
-rw-r--r--.  1 root root 644K Dec 20 04:22 modules.alias.bin
-rw-r--r--.  1 root root 1.3K Mar  6  2015 modules.block
-rw-r--r--.  1 root root 5.8K Mar  6  2015 modules.builtin
-rw-r--r--.  1 root root 7.5K Dec 20 04:22 modules.builtin.bin
-rw-r--r--.  1 root root 209K Dec 20 04:22 modules.dep
-rw-r--r--.  1 root root 304K Dec 20 04:22 modules.dep.bin
-rw-r--r--.  1 root root  339 Dec 20 04:22 modules.devname
-rw-r--r--.  1 root root  108 Mar  6  2015 modules.drm
-rw-r--r--.  1 root root  108 Mar  6  2015 modules.modesetting
-rw-r--r--.  1 root root 1.5K Mar  6  2015 modules.networking
-rw-r--r--.  1 root root  82K Mar  6  2015 modules.order
-rw-r--r--.  1 root root  165 Dec 20 04:22 modules.softdep
-rw-r--r--.  1 root root 285K Dec 20 04:22 modules.symbols
-rw-r--r--.  1 root root 356K Dec 20 04:22 modules.symbols.bin
lrwxrwxrwx.  1 root root    5 Dec 20 04:15 source -> build
drwxr-xr-x.  2 root root    6 Mar  6  2015 updates
drwxr-xr-x.  2 root root   91 Dec 20 04:15 vdso
drwxr-xr-x.  2 root root    6 Mar  6  2015 weak-updates
[root@localhost ~]# ll /boot/initramfs-`uname -r`.img -h
-rw-------. 1 root root 20M Jan 18 13:06 /boot/initramfs-3.10.0-229.el7.x86_64.img

在RHEL系列发行版中,/lib/modules/VERSION-RELEASE/中有对应内核所需的各种外围模块,依赖关系由内核(依赖关系文件modules.dep)处理

kernel目录中的内容为内核主要模块:

目录 说明
arch 平台相关,驱动CPU
crypto 加密解密
drivers 驱动
fs 文件系统
kernel 内核自身的额外功能
lib
mm Memory Management,内存管理
net 网络(不是驱动,而是网络协议栈的实现)
sound 声卡

另外,ramdis由于取药提供文件系统支持,而用户的情况有各不相同,故该文件在安装操作系统时生成,我们亦可自行使用工具生成之:

  • CentOS 5:mkinitrd
  • CentOS 6+:mkinitrddracut

六、init

内核初始化的最后一步就是启动 pid 为 1 的 init 进程。这个进程是系统的第一个进程。它负责产生其他所有用户进程

init 以守护进程方式存在,是所有其他进程的父进程

Init 系统能够定义、管理和控制 init 进程的行为。它负责组织和运行许多独立的或相关的始化工作(因此被称为 init 系统),从而让计算机系统进入某种用户预订的运行模式

仅仅将内核运行起来是毫无实际用途的,必须由 init 系统将系统代入可操作状态。比如启动外壳 shell 后,便有了人机交互,这样就可以让计算机执行一些预订程序完成有实际意义的任务。或者启动 X 图形系统以便提供更佳的人机界面,更加高效的完成任务。这里,字符界面的 shell 或者 X 系统都是一种预设的运行模式

大多数 Linux 发行版的 init 系统是和 System V 相兼容的,被称为 sysvinit。这是人们最熟悉的 init 系统。一些发行版如 Slackware 采用的是 BSD 风格 Init 系统,这种风格使用较少,本文不再涉及。其他的发行版如 Gentoo 是自己定制的。Ubuntu 和 RHEL 采用 upstart 替代了传统的 sysvinit

,启动系统的第一个进程,在RHEL系列的各个发行版中,该程序亦各不相同

  • CentOS5
    SysV init,进程串行启动
    配置文件:/etc/inittab
  • CentOS6
    Upstart,采用D-Bus、事件驱动模型等新机制4
    配置文件:/etc/inittab, /etc/init/*.conf
  • CentOS7

    Systemd

    配置文件:/usr/lob/systemd/system/etc/systemd/system

    完全兼容SysV脚本机制,service命令依然可用,建议使用systemctl命令来控制服务5

在 Linux 主要应用于服务器和 PC 机的时代,SysVinit 运行非常良好,概念简单清晰。它主要依赖于 Shell 脚本,这就决定了它的最大弱点:启动太慢。在很少重新启动的 Server 上,这个缺点并不重要。而当 Linux 被应用到移动终端设备的时候,启动慢就成了一个大问题。为了更快地启动,人们开始改进 sysvinit,先后出现了 upstart 和 systemd 这两个主要的新一代 init 系统

1. SysV init

2. Upstart init

3. systemd

七、初始化


  1. 引用自 https://zh.wikipedia.org/wiki/加电自检 ↩︎

  2. 相关规范:http://down.51cto.com/data/2459500 ↩︎

  3. 内容来自 https://zh.wikipedia.org/wiki/统一可延伸韧体介面 ↩︎

  4. 参考资料:https://en.wikipedia.org/wiki/D-Bus ↩︎

  5. 服务相关内容后续将做介绍 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章