ubuntu server-引导过程
BIOS/UEFI
打开黑箱看看里面
操作系统是如何启动的
三个彼此独立但相互关联的过程
1.Bios/UEFI自检过程(POST)
|
|
2.Boot Load加载执行过程
|
|
3.操作系统启动过程
|
|
BIOS
打开黑箱看看里面
主板芯片(计算机运行的第一个程序)
|
|
UEFI
打开黑箱看看里面
较新的主板支持UEFI (2015年以后)
|
|
安全引导(Secure-boot)
打开黑箱看看里面
|
|
硬盘分区表
打开黑箱看看里面
|
|
Boot Loader
打开黑箱看看里面
- BIOS/UEFI不关系统安装的操作系统
- POST自检结束后,BIOS/UEFI读取硬盘Boot Loader
- 读取并执行Boot L oder,由其引|导操作系统
- Linux世界里两大
Boot Loader程序
- LILO:基本已被废弃
- GRUB:目前绝大多数发行版采用
BIOS引导过程
打开黑箱看看里面
BIOS -> Boot Loader (GRUB2
)
第一阶段:boot.img读取并运行MBR
硬盘起始的446字节
第二阶段:boot.img 查找并运行core.img (通常位于MBR Gap)
core.img的任务是访问/boot/grub
,加载该目录下的所有模块
加载启动菜单,自动或手动选择进一步引导的系统内核
UEFI引导过程
打开黑箱看看里面
第一阶段
- UEFI读取
GPT
分区表,找到EFI分区
(格式Fat32 / 大小默认537M / boot esp ) - 从中读取、执行boot loader代码,加载模块
- 命令
parted
一print
(读的是文件:/boot/efi/EFl/ubuntu/ grubx64.efi)
|
|
第二阶段
- 查找
/boot/grub/x86_ 64- -efi/core.efi
执行 - 生成GRUB2菜单, 选择不同内核引导系统(内核二进制文件:
vmlinuz-<release- number>
) - 加载硬件驱动文件initrd.img到内存中,然后控制权交给内核,继续引导
- 系统加载systemd / upstart / init, 启动各服务
GRUB2
GRUB是一个强大的多引导加载程序
|
|
两种启动方式
|
|
操作系统引导的四个核心组件
|
|
GRUB菜单
GRUB菜单文件
|
|
显示菜单
|
|
单用户模式 类似于Windows启动时F8灾难恢复模式 BIOS: Shift UEFI: Esc
GRUB菜单
-“e"
-在引导项最后增加“single"
- Ctrl+ X
进入
手动生成GRUB菜单文件
|
|
安全风险
|
|
设置GRUB密码
|
|
以上明文存储GRUB密码存在风险隐患
|
|
其他BootLoader(LILO, Grub之外的)
1.SYSL INUX
|
|
2.EXTL INUX
|
|
3.ISOL .INUX
|
|
4.PXELINUX
- (无盘站–>无硬盘)
从网络服务器引导系统
的BootLoader - PXE(Pre-boot eXecution Environment)
- 使用DHCP为工作站分配IP
- 使用BOOTP加载BootLoader映像
- TFTP将引导映像传输至工作站(基于UDP协议)
/tftpboot/ pxelinux.0
: PXE BootLoader/tftpboot/ pxelinux.cfg
:配置文件- 目前新版支持NFS、HTTP、FTP服务器
系统无法启动!
两大问题原因
- 内核问题:手动安装内核时缺少模块、库文件(发行版错误)
- 驱动器故障:无法读取根驱动器
处理办法:
- 使用先前无故障版本内核引导系统
- 单用户模式(指定内核参数)
- 对于驱动器故障,可以使用救援盘(CD/DVD、USB) 检修硬盘:
fsck /dev/sda1
显示GRUB菜单
- 可以开机
一直按住ESC键、或SHIFT键
(在故障发生时,且没修改过grup菜单显示时)
操作系统启动
服务/Service (windows) ==后台/daemon (Linux)
INIT:内核引导后运行第一个程序INIT
,初始化操作系统并启动服务(直到关机)
- 内核加载后的初始化进程,用于启动其他程序
- 所有服务启动由init 程序处理(PID=1
) ,所有系统服务进程都是其子进程
- pstree -p 1
- /usr/sbin/init -> /lib/ systemd/systemd
现在的init
程序早已不是以前那个init,只是沿用,实则是个符号链接
- 早期版本配置文件:/etc/inittab
(ubuntu无此文件!
)
三种INIT
接上面
1.SysV / SysV-init 源自UNIX System V (目前老版本Linux还在使用)
2.Upstart 兼容SysV,Ubuntu意图用于替换SysV,其他发行版也有使用 几乎没有完整实现的Upstart(Ubuntu自己都不用Upstart了)
3.Systemd
目前主流发行版使用systemd-sysv
包兼容SysV格式的initd脚本
始于2010年,是目前最新的系统初始化后台程序;
速度更快,效率更高
SysV
- 分成不同运行级别的一组Shell脚本(哪些程序,什么时候运行)
- 每个程序有一个独立的脚本控制其启动或停止
- 系统启动时进入一个运行级(一组随系统启动的程序)
- 内核启动首先读取运行级别配置文件,决定进入哪个运行级
- 运行级别:
|
|
在不同运行级下启动程序的方法
方法1:/etc/ inittab
:定义不同运行级下启动的程序,每行定义一个应用程序
|
|
方法2:启动脚本
/etc/init.d/
下的脚本
/etc/rc1.d
为例是不同级别1下要运行的程序(符号链接),K
开头表示kill掉,S
是启动,后面数字的值代表优先级,最后面代表程序的名称
除了运行级,SysV也使用启动脚本控制程序启动、停止
启动脚本存放于/etc/init.d/
中,通过/etc/rcX.d/
目录调用(X 运行级)
脚本文件名S: Start
; K: Kill/Stop
, 数字表示优先级
(依赖顺序)
通过具体脚本启动停止程序稍嫌麻烦,系统包含工具指定脚本的运行级
|
|
action字段(在Ubuntu中已经找不到了)
- boot 进程在系统扃动时启动
- bootwait 进程在系统启动时启动,系统会等待它启动完成
- initdefault 系统默认进入的运行级别
- kbrequest 进程在按下特殊的组合键后启动
- once 当进入运行级别时,进程启动一次,后面down了也就不管了
- powerfail 系统关闭时才运行
- powerwait 系统关闭时才运行,系统将等待其运行完成
- respawn 进入运行级时启动,并在终止时重新启动(病毒可以这样,你杀掉之后过一会又会起来)
- sysinit 在boot和bootwait项之前启动
- wait 进程启动一次,系统等待其完成
查看系统运行级
|
|
更改运行级
|
|
Upstart
- 操作系统的复杂度不断上升,造成SysV脚本越来越复杂
- ubuntu官方开发Upstart用于替换SysV
- 处理可热插拔设备在Linux系统中造成的动态环境
- 使用公钥
/etc/init/
文件夹替代/etc/inittab 和/etc/init.d 中的启动脚本 - 每个程序和服务在init文件夹中都有一个
<program_name>.conf
配置文件
启动和停止服务
|
|
Linux Standard Base (LSB)
- 是一些Linux发行版协商共同支持的规范
- 目的是在不同Linux发行版之间创建一 致的使用体验
- LSB定义了标准的init命令:·
start、 stop、 restart
- 所有遵循L SB的Linux发行版都应该支持以上命令
- 但是Debian等发行方退出了LSB组织,目前ubuntu中不包含
|
|
Linux世界可能会日趋分裂,统一用户体验的缺失势必提高用户的学习成本
Sytemd(目前最主流)
-
由RedHat开发,并迅速流行于Linux世界
- Systemd 在系统初始化的方式上引入了一个主要的范式转换,并引起了一些争议
- 它放弃使用多 个小型初始化脚本,转而
使用单一程序
,配合每个服务独立的配置文件- 这违背了早期的Linux哲学(小而专著是性能、稳定、安全性的基础)
-
放弃了初始化脚本和运行级,Systemd创造了
target / unit
的概念unit
用来定义service、action- 由名称、类型、配置文件组成
- 常见unit类型
1
automount、 device、 mount、 path、 service、 snapshot、 socket、 target 等等
unit的命名方式
|
|
当前系统已加载的unit
|
|
Systemd 使用service类型的unit 管理后台服务
target 类型组合多个unit实现同时启动
|
|
配置unit
每个unit需要一个配置文件来定义需要启动、如何启动什么程序
配置文件路径/lib/systemd/system/
,不同版本,路径不尽相同
|
|
tartget配置文件
|
|
默认target
|
|
systemctl程序
|
|
兼容SysV
|
|
内核
Linux系统组成
- Linux内核
- GNU系统工具
- 图形化桌面环境
- 应用软件
内核控制计算机软硬件
- 由L inus Torvalds(当年是赫尔辛基大学的学生)创造,
- 直到目前为止的负责人(Linux Foundation)
操作系统的核心功能
-
管理系统的内存
-
管理软件程序
-
管理硬件
-
管理文件系统
-
如何安装内核(其不同的组成部分)?
-
如何创建新内核(支持新硬件和软件特性)?
-
如何管理内核及内核模块?
内存管理
- 在系统的内存容量限制下,控制程序如何运行
- 除管理物理内存,操作系统还负责创建和管理
虚拟内存
- 虚拟内存并非真实存在,它
利用硬盘空间
创建并当作真实内存使用(SWAP
) - 内核将一段时间不活跃的内容页转储到SWAP,并在需要时重新读入物理内存
Swapping out机制
使系统认为自己拥有更多可用的内存空间(降低性能)- 内存空间被分组到称为内存页的块中
- 内核定位物理内存或交换空间中的每个内存页
- 内核维护内存页表,登记哪些页位于物理内存/SWAP
- 虚拟内存并非真实存在,它
查看虚拟内存
|
|
Linux系统每个进程的内存彼此独立
|
|
共享内存页
|
|
查看当前系统共享内存页
|
|
软件程序管理
运行中的程序称为进程
|
|
查看当前进程
|
|
硬件管理
- 与系统通信的所有硬件都需要将驱动植入内核
|
|
- 内核模块是一个自包含的驱动程序库,可动态与内核链接/取消链接
- Linux系统的三种硬件设备文件
|
|
Linux为系统上的每个硬件设备创建称为节点的特殊文件
- 内核通过
唯一的数字对
标识每个节点(主
、次
) - 同类型设备主节点号相同,同一主节点号下,次节点号唯一
|
|
文件系统管理
文件系统定义OS如何在存储设备上存储数据
- 分区、格式化
- Linux 支持包括Windows在内的众多文件系统
- 内核统一使用Virtual File System (
VFS
) 与不同文件系统进行交互
内核的文件构成
内核二进制文件
- 内核程序本身,BootLoader加载到内存中执行的内容(位于
/boot
或/
中) - 基于编译打包的驱动数量不同,内核=进制文件可能很大
- 内核二进制文件通常被压缩,以便加载内核时节省内存空间
- 压缩方式不同,将导致内核二进制文件名称差异
不同的Linux内核文件 | 备注 |
---|---|
bzimage | (常用)GNU zip压缩的大内核,常被拷贝为4(vmlinuz) |
kernel | 未压缩 |
vmlinux | 未压缩,通常不用作最终的引导版本 |
vmlinuz | 通用的压缩文件(如ubuntu下:vmlinuz-4.15.0-65-generic) |
zimage | 使用GNU zip压缩的小内核 |
内核模块
内核直接与硬件交互
- 内核与硬件通信需要驱动程序的支持
- 将硬件驱动和内核的
源码
一并编译成二进制执行文件(体积大) - 将驱动编译为二进制的模块对象文件
.ko
, 运行时动态链接
硬件驱动的发布
- 源码:开源精神
- 二进制文件:保护隐私、功能特性
内核模块(modprob
)
|
|
内核源码
获得
- Linux内核开发库(www.kernel.org –> 稳定版、开发版)
- 对应Linux发行版的软件库(对本发行版最稳妥,下载方便)
- 下载源码解压至
/usr/src/linux
(内核工具默认查找路径)
|
|
内核补丁
- 针对bug修复和安全补丁的增量内核发行版
- 内核补丁版本(
针对主版本的补丁
)- 只包含应用于主内核源代码发行版以获得增量发行版的
更改
(5.3 –> 5.3.1) - 使用
patch
命令将补丁源码包应用于主源码包,然后重新编译
- 只包含应用于主内核源代码发行版以获得增量发行版的
- 后续补丁版本(5.3.1 -> 5.3.2)
- 卸载早期版本补丁(
patch -R
) - patch新版本补丁
- 重新编译
- 卸载早期版本补丁(
内核头
Linux内核绝大部分使用C语言编写 - C语言头文件:编译时需要的库文件 - 编译内核、模块都需要相同的内核头(库文件)
Ubuntu内核头
|
|
内核文档
- 许多独立的文本文件,说明每个源代码文件在内核结构中的作用
- 针对内核源码做任何操作之前,建议详细阅读文档
- 由于文档体量巨大,通常以独立包形式发布
- 文档路径
|
|
内核版本
-
七个内核版本命名方式(系统)
-
Linus于1991年9月发布了初始Linux内核版本号0.01
- 0表示该版本目的是测试,并非生产环境使用(延用至0.95 – 1 992.3)
-
1994年3月,Linus 发布了Linux 的第一个生产版本1.0 (
1.x.y
)- x主版本号(
奇数
表示测试/开发版本;偶数
表示稳定/生产版本) - y主版本下的补丁版本
- 此版本号延用至 1.3 (1995.5)
- x主版本号(
-
1.3之后Linux内核变化很大,因此下一个版本为2.0 (1996.6)
-
2.x.y延用1.x.y 的命名方式,直至2.4 (2001.1)
-
2003.12 Linus发布2.6.0版本,启动了一个新的版本命名系统
- 由于2.6内核非常稳定,因此新内核版本格式为2.6.x.y(
不再通过奇偶数来区分稳定与否
) - 2.6 每个版本都是生产版本(
开发版结尾为-rc
) - 此版本延用至2.6.39 (2011.5)
- 由于2.6内核非常稳定,因此新内核版本格式为2.6.x.y(
-
2011.7 Linus为庆祝Linux内核20岁生日,启动了内核的3.0版本
- 3.x.y (开发版在结尾加-rc) -直延用至3.19 (2015.2)
- 3.x.y-z 临时特殊补丁版(主要与紧急的安全修复有关)
-
2015.4发布4.0版本
- 4.x.y (与3.0相同)
- 4.x.y-z (y的第z次
微调
版本)
-
2019.3发布5.0版本
- 目前最新,命名延用以前
查看内核版本
|
|
维护内核
- 手动编译内核(较少使用,忽略)
- 使用发行版包管理器维护内核(建议的方式)
- 模块文件
|
|
- 手动编译内核模块,当升级内核时需要重新编译模块
- Dynamic Kernel Module Support (
DKMS
) - 注册自定义模块后,dkms监视内核变化,并自动运行脚本重新编译安装模块
- Dynamic Kernel Module Support (
常用模块命令
|
|
内核排错
查看内核版本
|
|
/proc目录
|
|