本文共 8607 字,大约阅读时间需要 28 分钟。
BIOS(基本输入输出系统
),该系统存储于主板的ROM
芯片上,计算机在开机时,会最先读取该系统,然后会有一个加电自检过程。这个过程其实就是检查CPU和内存,计算机最基本的组成单元(控制器、运算器和存储器),还会检查其他硬件,若没有异常就开始加载BIOS程序到内存当中。BIOS的功能大概可以分为3个部分:
用于电脑刚接通电源时对硬件部分的检测,也叫做加电自检(Power On Self Test
,简称POST
)。功能是检查电脑是否良好,通常完整的POST自检将包括对CPU,640K基本内存,1M以上的扩展内存,ROM,主板,CMOS存储器,串并口,显示卡,软硬盘子系统及键盘进行测试,一旦在自检中发现问题,系统将给出提示信息或鸣笛警告。自检中如发现有错误,将按两种情况处理:
初始化硬件(这个玩过开发板的应该都很清楚)。包括创建中断向量、设置寄存器、对一些外部设备进行初始化和检测等,其中很重要的一部分是BIOS设置,主要是对硬件设置的一些参数,当电脑启动时会读取这些参数,并和实际硬件设置进行比较,如果不符合,会影响系统的启动。
引导操作系统程序。BIOS
会按照硬盘的引导记录去查找第一个磁盘头的MBR信息,并加载和执行MBR
中的Bootloader
程序,若第一个磁盘不存在MBR,则会继续查找第二个磁盘(启动顺序可以在BIOS
的界面中进行设置),一旦BootLoader
程序被检测并加载内存中,BIOS
就将控制权交接给了BootLoader
程序(控制权交接其实就是指CPU跳转到Bootloader
程序的内存位置执行)
MBR(Master Boot Record
)主引导记录,MBR存储于磁盘的头部,大小为512 bytes
,组成为:[446 bytes
(存储BootLoader
程序)+64 bytes
(存储分区表信息)+2 bytes
(用于MBR
的有效性检查)]。
这个部分就需要分为3个阶段来执行了:
BIOS加载它找到的第一个引导记录(MBR)中到内存中,并开始执行此代码。Bootloader
必须非常小,因为它必须连同分区表放到硬盘的第一个 512 字节的扇区中。 在传统的常规 MBR 中,引导代码实际所占用的空间大小为 446
字节。这个MBR中这个 446
字节的文件通常被叫做引导镜像(boot.img)
,其中不包含设备的分区信息,分区是一般单独添加到引导记录中。
由于boot.img
必须做的非常小,所以基本不可能有太多复杂的功能,他唯一能做的就是加载Stage_1.5中的存储的代码,也就是core.img
( 25389 25389 25389字节)。该文件通常位于MBR与第一个分区之间,也就是 0 ∼ 63 0\sim63 0∼63扇区之间(未包括 63 63 63),总大小为 62 ∗ 512 = 31744 62*512=31744 62∗512=31744字节。这个文件,存放了一些通用的文件系统驱动程序,如标准的 EXT
和其它的 Linux
文件系统,如 FAT
和 NTFS
等。所以这阶段就是负责执行Stage_1.5
中存放的驱动程序,并加载相关的驱动程序。
Grub2
的core.img
远比老一版的Grub1
更复杂且更强大。这意味着Grub2
的core.img
能够放在标准的EXT
文件系统内,但是不能放在逻辑卷内。故在Grub2
中,Stage_1.5
中的文件可以存放于/boot
文件系统中,一般在/boot/grub2
目录下。
进入Stage_2
时,所有的文件(内核、initrd
等)都已存放于/boot
目录及其几个子目录之下。同时,该阶段还可以从 /boot/grub2/i386-pc
目录下加载一些内核运行时模块。所以Stage_2
的主要功能是定位和加载 Linux 内核和initrd
到内存中,并转移控制权。
在linux
启动时按下C
即可进入Grub2
的命令行模式,这里你可以自己手动引导内核和initrd的加载。关于手动引导的相关操作,可以自行百度。这里我们重点来看下配置文件/boot/grub2/grub.cfg
,这里有篇文章已经说得很详细,这里就直接与大家分享了:
由于Linux内核是很精简的,只保留必要的驱动程序,而现实中的设备种类繁多,例如:根文件系统可以存储在包括IDE、SCSI、USB在内的多种介质上,如果将这些设备的驱动都编译进内核那该多么臃肿,所以就干脆将设备特有的驱动与内核分离,单独形成initrd
(一般自己编译的系统不需要,发行版需要兼容所以会需要)。需要哪种驱动就提取到initrd
中,待启动时提前加载即可。所以内核启动一般分两步:
在 linux
内核启动前, bootloader
会将存储介质中的 initrd
文件加载到内存,内核启动时会在访问真正的根文件系统前先访问该内存中的 initrd
文件系统,这个过程将会完成相关驱动模块的加载,最主要就是加载根文件系统存储介质的驱动模块等,这样内核就可以正常识别设备和真正的根文件系统了。
initrd( boot loader initialized RAM disk),就是由
bootloader
初始化的内存盘,算是一个很mini版的文件系统。
之后,内核会以只读方式挂载根文件系统,当根文件系统被挂载后,开始装载第一个进程(用户空间的进程),执行/sbin/init
,之后就将控制权交接给了init程序。如果是使用systemd的话,则是加载systemd
进程到内存中。
这一节呢,我们分为两个init
系统来叙述:
sysvinit
就是 System V
风格的 init
系统,顾名思义,它源于 System V
系列的 UNIX
。最初的 linux
发行版几乎都是采用 sysvinit
作为 init 系统。sysvinit
用术语 runlevel 来定义 “预订的运行模式”。比如
这个初始化系统的涉及到的配置文件如下(按init进程读先后顺序):
####省去多余注释##########表示当前缺省运行级别为5(initdefault),即默认以图形界面启动id:5:initdefault:###启动时自动执行/etc/rc.d/rc.sysinit脚本(sysinit)# 这一项表示在系统启动时执行/etc/rc.d/rc.sysinit程序si::sysinit:/etc/rc.d/rc.sysinitl0:0:wait:/etc/rc.d/rc 0l1:1:wait:/etc/rc.d/rc 1l2:2:wait:/etc/rc.d/rc 2# 当切换到runlevel3(命令行模式时),执行一下/etc/rc.d/rc这个程序,并传递参数3l3:3:wait:/etc/rc.d/rc 3l4:4:wait:/etc/rc.d/rc 4###当运行级别为5时,以5为参数运行/etc/rc.d/rc脚本,init将等待其返回(wait)l5:5:wait:/etc/rc.d/rc 5#这个就是同时匹配多个runlevell6:23456:wait:/etc/rc.d/rc 6
每个配置项格式如下:
i d : r u n l e v e l : a c t i o n : p r o c e s s id:runlevel:action:process id:runlevel:action:process
各项含义如下:
id
id是指入口标识符,它是一个字符串,对于getty或mingetty等其他login程序项,要求id与tty的编号相同,否则getty程序将不能正常工作。
runlevel
runlevel是init所处于的运行级别的标识.runlevel可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevel与当前运行级别匹配成功才会执行
action
respawn
:当process终止后马上启动一个新的wait
:当进入指定的runlevels后process才会启动一次,并且到离开这个runlevels终止initdefault
:设定默认的运行级别,即我们开机之后默认进入的运行级别,不能是0,6,你懂的sysinit
:系统初始化,只有系统开机或重新启动的时候,这个process才会被执行一次powerwait
:当init接收到电源失败信号的时候执行相应的process,并且如果init有进程在运行,会等待这个进程完成之后,再执行相应的processpowerfail
:当init接收到电源失败信号的时候执行相应的process,并且如果init有进程在运行,不会等待这个进程完成,它会直接执行相应的processpowerokwait
:电源已经故障,但是在等待执行对应操作的时候突然来电了就执行对应的processpowerfailnow
:当电源故障并且init被通知UPS电源已经快耗尽执行相对应的processctrlaltdel
:当用户按下ctrl+alt+del这个组合键的时候执行对应的processboot
:只有在引导过程中,才执行该进程,但不等待该进程的结束;当该进程死亡时,也不重新启动该进程bootwait
:只有在引导过程中,才执行该进程,并等待进程的结束;当该进程死亡时,也不重新启动该进程off
:如果process正在运行,那么就发出一个警告信号,等待20秒后,再通过杀死信号强行终止该process。如果process并不存在那么就忽略该登记项once
:启动相应的进程,但不等待该进程结束便继续处理/etc/inittab文件中的下一个登记项;当该进程死亡时,init也不重新启动该进程process
表示启动哪个程序或脚本或执行哪个命令
所有的运行级别下,init依赖/etc/rc.d/rc.sysinit
这个脚本对系统进行初始化。按照下面的顺序按部就班的初始化系统:
/etc/sysctl.conf
中的内核参数这个程序就是根据传入的参数,调用/etc/rc.d/rc0.d~rc6.d
中的相应的脚本程序,来完成相应的初始化工作和启动相应的服务,最后调用/etc/rc.d/rc.local
,这个文件里面可以放一些用户自定义的启动脚本等等
systemd 是 linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit
固有的缺点,提高系统的启动速度。
在开始看Systemd
进程做的事情之前,请先了解一下开机启动脚本的编写和选项含义,这里直接推荐一篇不错的文章:。新旧系统运行等级映射关系如下:
SystemV 运行级别 | systemd 目标态 | systemd 目标态别名 | 描述 |
---|---|---|---|
halt.target | 停止系统运行但不切断电源。 | ||
0 | poweroff.target | runlevel0.target | 停止系统运行并切断电源. |
S | emergency.target | 单用户模式,没有服务进程运行,文件系统也没挂载。这是一个最基本的运行级别,仅在主控制台上提供一个 shell 用于用户与系统进行交互。 | |
1 | rescue.target | runlevel1.target | 挂载了文件系统,仅运行了最基本的服务进程的基本系统,并在主控制台启动了一个 shell 访问入口用于诊断。 |
2 | runlevel2.target | 多用户,没有挂载 NFS 文件系统,但是所有的非图形界面的服务进程已经运行。 | |
3 | multi-user.target | runlevel3.target | 所有服务都已运行,但只支持命令行接口访问。 |
4 | runlevel4.target | 未使用。 | |
5 | graphical.target | runlevel5.target | 多用户,且支持图形界面接口。 |
6 | reboot.target | runlevel6.target | 重启。 |
default.target | 这个目标态target是总是 multi-user.target 或 graphical.target 的一个符号链接的别名。systemd 总是通过 default.target 启动系统。default.target 绝不应该指向halt.target 、poweroff.target 或 reboot .target。 |
Systemd
进程在被加载到内后,将依次执行五个目标:
/usr/lib/systemd/system/default.target
,这个文件链接到当前目录的graphical.target
[Unit]Description=Graphical InterfaceDocumentation=man:systemd.special(7)Requires=multi-user.targetWants=display-manager.serviceConflicts=rescue.service rescue.targetAfter=multi-user.target rescue.service rescue.target display-manager.serviceAllowIsolate=yes
default.target
强依赖于multi-user.target
,所以接下来这步就要执行如下两个目录中的目标了:/etc/systemd/system/multi-user.target.wants/
/usr/lib/systemd/system/multi-user.target.wants/
大部分的用户程序的目标都在这两个目录下有配置,在这步就一并启动了
#/usr/lib/systemd/system/multi-user.target.wants/multi-user.target[Unit]Description=Multi-User SystemDocumentation=man:systemd.special(7)Requires=basic.targetConflicts=rescue.service rescue.targetAfter=basic.target rescue.service rescue.targetAllowIsolate=yes
basic.target
目标了,内容如下:/etc/systemd/system/basic.target.wants/
/usr/lib/systemd/system/basic.target.wants/
#/usr/lib/systemd/system/multi-user.target.wants/basic.target[Unit]Description=Basic SystemDocumentation=man:systemd.special(7)Requires=sysinit.targetAfter=sysinit.targetWants=sockets.target timers.target paths.target slices.targetAfter=sockets.target paths.target slices.target
sysinit.target
会启动重要的系统服务例如系统挂载,内存交换空间和设备,内核补充选项./etc/systemd/system/sysinit.target.wants/
/usr/lib/systemd/system/sysinit.target.wants/
[Unit]Description=System InitializationDocumentation=man:systemd.special(7)Conflicts=emergency.service emergency.targetWants=local-fs.target swap.targetAfter=local-fs.target swap.target emergency.service emergency.target
local-fs.target
,它不会启动用户相关服务,它只处理底层核心服务,这个target会根据/etc/fstab
来执行相关磁盘挂载操作/usr/lib/systemd/system/xx服务.service
:官方默认配置文件,不建议修改这个位置的文件,而应该像下面这项这样操作;/etc/systemd/system/xx服务.service.d/custom.conf
:在 /etc/systemd/system
下面创建与配置文件相同文件名的目录,但是要加上 .d
的扩展名。然后在该目录下创建配置文件即可。另外,配置文件最好附文件名取名为 .conf
。 在这个目录下的文件配置会合并到 /usr/lib/systemd/system/xx服务.service
。/etc/systemd/system/xx服务.service.wants/*
:此目录内的文件为链接文件,设置相依服务的链接。意思是启动了 xx服务.service 之后,最好再加上这目录下面建议的服务。/etc/systemd/system/xx服务.service.requires/*
:此目录内的文件为链接文件,设置相依服务的链接。意思是在启动 xx服务.service 之前,需要事先启动哪些服务的意思。在sysvinit系统中,由于/etc/inittab
中的配置如下:
1:2345:respawn:/sbin/mingetty tty12:2345:respawn:/sbin/mingetty tty23:2345:respawn:/sbin/mingetty tty34:2345:respawn:/sbin/mingetty tty45:2345:respawn:/sbin/mingetty tty56:2345:respawn:/sbin/mingetty tty6# 只有我们进入5运行级别,会打开图形用户终端,并且一旦终端终止,就会再创建一个新的x:5:respawn:/etc/X11/prefdm -nodaemon
在2345运行级别下,会调用/sbin/mingetty
启用6个命令行界面的终端,并且一旦终端终止,就会再创建一个新的。
在上面初始化的第1步中等待了display-manager.service
这个服务就是用于启动终端界面的,内容如下:
[Service]ExecStart=/usr/sbin/gdmExecStartPost=-/bin/bash -c "TERM=linux /usr/bin/clear > /dev/tty1"KillMode=mixedRestart=alwaysIgnoreSIGPIPE=noBusName=org.gnome.DisplayManagerStandardOutput=syslogStandardError=inheritEnvironmentFile=-/etc/locale.confExecReload=/bin/kill -SIGHUP $MAINPID[Install]Alias=display-manager.service
转载地址:http://xqfen.baihongyu.com/