请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

用无盘启动 volumio 顺便研究一下 linux 启动原理

[复制链接]
gaosmile 发布时间:2020-11-23 21:05
0. 故事的开始
) a' x, J$ b5 F* l& i8 ^1 j( C" X- i  W
% h) e" A) j* g7 `: b8 \
0.1 为什么和做什么
最近家里买了对音响,我需要一个数字播放器。一凡研究后我看上了 volumio(https://volumio.org/) 这是一个基于 Debian 二次开发的 HIFI 播放器系统,可以运行下 x86 和树莓派上。
我打算让 volumio 运行在我 2009 年购买的老爷机笔记本上,也让它发挥一点余温热。正常操作是将 volumio 的系统镜像刷到 U 盘上,连接电脑后使用 U 盘启动系统即可。但是家里没有找到合适的 U 盘(穷~~),加上前段时间听了同事关于 linux 内核的分享,感慨自己对系统的理解不够。因此我决定使用无盘启动 volumio 顺便研究一下 linux 启动原理。
目标:无盘启动 volumio 系统
0.2 方案
正常 Linux 启动流程大体如下:
  • BIOS 启动,完成自检,选择启动硬件
  • 如果是磁盘系统读取 MBR
  • 从 MBR 指示,找到 GRUB 所在分区,加载 GRUB 显示菜单
  • 加载 Linux 内核到内存中
  • 执行 INIT 程序
  • 进入用户界面
    - `* O' ?$ {: H) c/ k) e2 y$ c
微信图片_20201123210055.png
由于我需要从网络启动,过程会变得复杂一些,主要变化如下
  • 在 MBR 引导前,需要执行一系列的 PXE 流程,目的是挂载 iscsi 磁盘。
  • 在加载 linux 内核后,由于之前 iPXE 固件已经退出,还需要再次挂载 iscsi 磁盘。
    ! V# o" F" Z3 ]: U
微信图片_20201123210059.png 6 V2 h2 }4 i# B. n4 r
/ ~# c; z  \" M* t5 {
3 L) y, O" \0 x( P: |; W8 O
0.3 准备工作
无盘启动并不是说完全没有磁盘,只是客户端本身没有磁盘,我们需要在远端给机器提供一种文件存储和磁盘共享的方案。我这里选择的是 iscsi 共享,相比于 NFS 和 samba 共享,它更底层,对系统的兼容性更好。
iSCSI 利用了 TCP/IP 作为沟通的渠道。透过两部计算机之间利用 iSCSI 的协议来交换 SCSI 命令,让计算机可以透过高速的局域网集线来把 SAN 模拟成为本地的储存设备。
关于 iscsi 的配置不是本文重点,这里就不详细描述了,要完成 iscsi 磁盘的挂载需要接信息。
iscsi 服务器地址:我这里是 nas 服务的地址 192.168.3.5
target 名称:这个是服务端用来区分目标的,通常一个 target 服务一个客户端,并关联一块共享存储,例如:iqn.2005-10.org.freenas.ctl:yong-pc.volumio
initiator 名称:这个是客户端名称,用来告诉服务端谁来请求了。
1 BIOS 和 UEFI
准备工作做完,我们先来了解一下计算机的启动原理,这里就要说到 BIOS 和 UEFI,他们是计算机按下电源后最先被执行的程序。
1.1 BIOS (Basic Input/Output System)
上个世纪 70 年代初,"只读内存"(read-only memory,缩写为 ROM)发明,开机程序被刷入 ROM 芯片,计算机通电后,第一件事就是读取它。这块芯片里的程序叫做"基本输入输出系统"(Basic Input/Output System),简称为 BIOS。
微信图片_20201123210104.png
BIOS 程序首先检查,计算机硬件能否满足运行的基本条件,这叫做"硬件自检"(Power-On Self-Test),缩写为 POST。硬件自检完成后,BIOS 把控制权转交给下一阶段的启动程序。
这时,BIOS 需要知道,"下一阶段的启动程序"具体存放在哪一个设备。也就是说,BIOS 需要有一个外部储存设备的排序,排在前面的设备就是优先转交控制权的设备。这种排序叫做"启动顺序"(Boot Sequence)。
微信图片_20201123210107.png
, p$ r" u- O# x! V% w) A6 |
, _$ O, [1 J# H( a
  E8 J7 `9 R: j
1.2 UEFI (Unified Extensible Firmware Interface)
不知道大家是否发现,这些年已经很难看到 BIOS 的身影了。
ROM 的存储能力有限,BIOS 能驱动的硬件类型和数量大大受限。导致大量新硬件无法在 PC 启动时被加载。最明显就是你无法在 BIOS 时使用鼠标。此外 BIOS 的代码历史悠久难以维护。
在 2005 年年中时候,包括 BIOS 供应商、OS 供应商、系统制造商以及芯片生产公司在内的行业参与者统一建立了统一的 EFI 联盟(UEFI,Unified Extensible Firmware Interface)并在 2006 年一月发行了 UEFI 规范 2.0。
从此你可以愉快的在 PC 启动初期使用鼠标,甚至像苹果一样加载网络,实现联网下载并安装操作系统。
微信图片_20201123210111.png
UEFI 的启动流程和 BIOS 的启动流程不同,由于我 2009 年购买的老爷机还是 BIOS 结构,这里不详细展开,简单提一下。
  • 系统开机 - 上电自检(Power On Self Test 或 POST)。
  • UEFI 固件被加载,并由它初始化启动要用的硬件。
  • 固件读取其引导管理器以确定从何处(比如,从哪个硬盘及分区)加载哪个 UEFI 应用。
  • 固件按照引导管理器中的启动项目,加载 UEFI 应用。
  • 已启动的 UEFI 应用还可以启动其他应用(对应于 UEFI shell 或 rEFInd 之类的引导管理器的情况)或者启动内核及 initramfs(对应于 GRUB 之类引导器的情况),这取决于 UEFI 应用的配置
    5 Q/ e( S$ _  S6 r0 L
2. PXE
回到我的 BIOS 老爷机,上电自检完成后 BIOS 按照设置的启动顺序应该交棒磁盘,但是 但是 但是 这个机器没有硬盘,也没有插入 U 盘,找不到任何启动设备的 BIOS 将控制权交给了网卡,BIOS 光荣退场进入了 PXE 阶段。
预启动执行环境(Preboot eXecution Environment,PXE,也被称为预执行环境)提供了一种使用网络接口启动计算机的机制。这种机制让计算机的启动可以不依赖本地数据存储设备(如硬盘)或本地已安装的操作系统。
微信图片_20201123210114.png
- X7 q! A4 }  R: T& @
# H! o+ e# W6 c- N: L: F4 L) C8 i. F* E
1 i6 R* Y5 w# n/ Y! q. J
2.1 PXE 原理
  • Client 向 DHCP 发送 IP 地址请求消息,DHCP 返回 Client 的 IP 地址,同时将启动文件(如:pxelinux.0)的位置信息(通常是 TFTP 路径)一并传送给 Client
  • Client 向 TFTP 发送获取启动文件请求消息,TFTP 接收到消息之后再向 Client 发送启动文件大小信息,试探 Client 是否满意,当 TFTP 收到 Client 发回的同意大小信息之后,正式向 Client 发送启动文件 Client 执行接收文件
  • Client 向 TFTP 发送针对本机的配置信息文件请求,TFTP 将配置文件发回 Client,继而 Client 根据配置文件执行后续操作。
  • Client 会加载启动文件,之后根据配置执行动作。这里有多重方案进行下一步操作。( X1 v1 G/ k9 E' y) [- a
    • 可以直接通过 Http 协议获取 Linux kernel 和 ramdisk 然后启动
    • 或者加载一块 iscsi 磁盘,将 linux kernel 和 ramdisk 等信息放在 iscsi 磁盘中,走正常磁盘引导。我用的是这种方案
      ) G6 |; p! @6 `8 Z  g0 C
微信图片_20201123210117.png # D& w% q$ Z  b5 H

7 m* A+ u% p" g  R% x# X. C$ G

7 b# h( C& U7 [9 r! `2.2 iPXE
上面说到了启动文件,普通的 pxe 启动文件功能有限,通常只能从 tftp 服务器上获取文件,不支持 HTTP 协议和其他共享协议,更别说我们要支持的 iscsi 磁盘挂载了。这里推荐一个高端开源 pxe 启动文件:iPXE(https://ipxe.org/)。它支持从 HTTP、iscsi SAN、 Fibre Channel SAN、AoE SAN 等多种方式启动,甚至还支持无线网卡。此外它还可以定制一个启动脚本和菜单。
iPXE 需要根据自己硬件对应的平台进行编译,编译前需要搞清楚几个要点:
  • 启动方式:BIOS 或者 EFI 前面已经说了。
  • 平台:X86 或 ARM,如果用树莓派等产品就是 ARM,PC 是 x86
  • CPU 位:32 或 64,32 位机器只支持 32 位固件,64 位机器可以兼容 32 位和 64 位固件。注意:如果使用 64 位固件需要保证后续所有环节使用兼容 64 位的软件,我就遇到了 SysLinux 不支持 64 位,导致卡死的问题。
    8 |4 s9 C* n) X% V! c- s1 I
使用如下命令编译(更多细节见:https://ipxe.org/appnote/buildtargets):
git clone git://git.ipxe.org/ipxe.git
- {6 b& g% H+ e- B4 N( Amake [platform]/[driver].[extension]
2 x' s+ X8 K/ O
Platform 支持如下:按照上面说的启动方式、平台、CPU 情况选择。
  • bin (alias for bin-i386-pcbios)
  • bin-i386-pcbios
  • bin-i386-efi
  • bin-i386-linux
  • bin-x86_64-efi
  • bin-x86_64-linux
  • bin-x86_64-pcbios
  • bin-arm32-efi
  • bin-arm64-efi2 {, t7 I/ Z' p  Y; h3 R. k
Driver:主要选择支持的网卡驱动类型,一般选 ipxe(表示所有支持的网卡,但可能导致生成的启动文件过大,如果过大可以酌情选其它)
Boot type:和启动方式、启动介质有关,参考下表:
微信图片_20201123210120.png
编译时添加 EMBED={脚本名称} 可以关联一个启动脚本。推荐一个大佬做好的脚本 http://boot.netboot.xyz/menu.ipxe 可以直接使用。
我最终命令如下:
git clone git://git.ipxe.org/ipxe.git2 e7 i- Q% m' z, R$ m9 a
cd ./ipxe/src( l  f4 b- c9 j
wget http://boot.netboot.xyz/menu.ipxe; M+ t0 _. `8 E
make bin-i386-pcbios/ipxe.pxe EMBED=menu.ipxe
; C8 K' u7 R  l# V
完成之后在/data/ipxe/src/bin-i386-pcbios/ipxe.pxe 可以拿到最终的启动文件。
2.3 DHCP、TFTP 配置
如何配置 DHCP 和 TFTP 服务器不是本文重点,如果需要命令行方式配置可以参考这篇文章的前半部分https://blog.51cto.com/dyc2005/2068188
如今大部分高端路由器或开源路由器固件都内置了 DHCP 和 TFTP 配置功能。我家的 LEDE 路由器配置界面如下。
  • 微信图片_20201123210123.png
  • TFTP 服务器根目录:这个是启动文件、配置文件存放的目录路径(是在路由器上的路径,可以放在 u 盘挂上去,也可以直接放在路由器存储的目录
  • 网络启动镜像:这是对客户端下发的启动文件名称。(不同 CPU 架构,不同平台的文件名不同)% `2 X* ]2 d) u5 W7 f
拷贝之前编译好的 ipxe.pxe 和 menu.ipxe 文件到/www/pxe/目录下,并设置网络启动镜像为:ipxe.pxe
配置正确,启动后就可以看到如下选择界面了:
微信图片_20201123210126.png ) G. O7 u9 l6 D1 k' r: U+ Y

9 N! \8 f7 |8 b( ~  I

* k0 Z+ d- [! K# [" w9 p3. 分区:MBR 和 GPT
ipxe 完成使命后,正式交棒给磁盘,如果你是硬盘启动,可以直接跳过第 2 部分,直接到这一步。这一阶段系统需要从磁盘上找到启动文件并加载。在说如何找到启动文件前,先要说说硬盘是如何划分区块的,主要有两大方式 MBR 和 GPT。我们先来聊一下机械硬盘的工作原理。
机械硬盘由坚硬金属材料制成的涂以磁性介质的盘片,盘片两面称为盘面或扇面
假设磁头不动,硬盘旋转,那么磁头就会在磁盘表面画出一个圆形轨迹并将之磁化,数据就保存在这些磁化区中,称之为磁道,将每个磁道分段,一个弧段就是一个扇区。一个硬盘可以包含多个扇面,扇面同轴重叠放置,每个盘面磁道数相同,具有相同周长的磁道所形成的圆柱称之为柱面,柱面数与磁道数相等。如下图:
微信图片_20201123210129.png
最初的寻址方式称为 CHS,所谓 CHS 即柱面(cylinder)磁头(header)扇区(sector),通过这三个变量描述磁盘地址。
3.1 MBR
说了这么多还是没说明白到底计算机怎么从磁盘上找到引导程序。答案是:它被固定写死在了 0 柱面,0 磁头,1 扇区的位置通常是 512byte,这个位置被称为主扇区(Master Boot Record, MBR)。
MBR 主要包含如下数据:
  • 主引导记录(bootloader),负责从活动分区加载并运行系统引导程序。446 字节
  • 硬盘分区表项(DPT——disk partition table),由四个分区表项组成,负责记录磁盘的分区情况。64 字节。
  • 硬盘有效标志(magic number),代表引导扇区结束,占用 2 字节。
    7 o' J3 T0 g* Z% k+ x) H1 E4 H
微信图片_20201123210133.png
Bootloader:这部分记录了一段较小引导代码,用于去启动硬盘其他分区位置上更大的引导文件,例如 linux 操作系统的 grub 目录。
微信图片_20201123210135.png
我们知道一个硬盘的每个分区的第一个扇区叫做 boot sector,这个扇区存放的就是操作系统的 loader。如上图,第一个分区的 boot sector 存放着 windows 的 loader,第二个分区放着 Linux 的 loader,第三个第四个由于没有安装操作系统所以空着。至于 MBR 的 bootloader 是干嘛呢, bootloader 有三个功能:
  • 提供选单:让用户选择进入哪个系统。
  • 读取内核文件:默认启动的 loader 会被拷贝一份到 MBR 中,这样就可以直接读取内核了,图中 1 部分
  • 转交给其他 loader:图中 2,3 部分0 q5 w6 K6 k0 |! S% r6 H
Disk Partition table:这一部分 64 字节大小被均分为 4 份,每份大小 16 字节,每当我们在硬盘上创建出一个新的主分区或者扩展分区时,便会占用 1 个 16 字节的大小用于记录这个分区的相关信息(例如起始和截止柱面位置、分区文件系统类型等等)。这就是为什么 mbr 分区模式最多只能有 4 个主分区的原因。
MBR 的局限:
  • 最多只支持 4 个主分区,超过 4 个就需要使用扩展分区。
  • 磁盘的最大容量只能到 2.2TB9 w8 j: }! N& z- \) b" \& M! F
如今我家的硬盘都 4T 了,MBR 早就不能满足需求了。你也不能怪 MBR,毕竟人家 1983 年就提出了,比我的年纪还大。
3.2 GPT
为了解决 MBR 的问题,GPT 分区诞生,GPT 全称 Globally Unique Identifier Partition Table,也叫 GUID 分区表,它是 UEFI 规范的一部分(但这并不是说它只支持 UEFI,它也支持 BIOS 方式的引导)。
微信图片_20201123210139.png
GPT 分区结构如下:
  • Protective MBR:GPT 分区表的最前面部分也保存了和 MBR 相同的格式和内容称为 Protective MBR,这极大的提高了 GPT 分区表的兼容性。
  • 主 GPT Header:这里记录了分区表项目数和每项目大小。
  • 主 GPT 分区表:包含分区的类型 GUID,名称,起始终止位置,该分区的 GUID 以及分区属性
  • 实际分区
  • 备份 GPT 分区表: 用于提高安全性,防止主 GPT 分区表损坏
  • 备份 GPT Header: 用于提高安全性,防止主 GPT Header 损坏& d' m. h- x3 j0 T+ ]: V: _
3.3 Bootloader 写入
使用 dd 命令结合 hexdump 可以输出 MBR 信息
dd if=~/Desktop/volumio-2.799-2020-07-16-x86.img ibs=512 count=1 | hexdump -C
& ]" e6 J' D) E) {! s- c  Z+ I
微信图片_20201123210142.png
同样的使用 dd 命令可以拷贝 MBR 信息从 img 文件到物理磁盘。(之前我是分分区写入到磁盘的,导致 MBR 信息丢失无法引导)% C- \( f* o  f$ Z  @
dd if=~/Desktop/volumio-2.799-2020-07-16-x86.img ibs=512 count=1 of=/dev/sda
' |1 O  K; G/ u7 p: F
也可以使用下载的 syslinux 中的 mbr.bin 写入
dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/mbr.bin of=/dev/sda //MBR分区表) S) W* q* S! L" s2 i
dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/gptmbr.bin of=/dev/sda //GPT分区表
- P3 F9 X/ s/ A; [
4. 引导加载程序:Syslinux 和 GRUB
前文说到 MBR 的 bootloader 主要功能是交棒内核,但是 bootloader 不会直接拉起 linux 内核,400K 太小,它没有能力将 linux 内核直接加载到内存。这时需要引导加载程序登场,它的主要目的就是将系统内核镜像和 initrd 镜像加载到内存并将控制权交给它们。目前常用的有两种 Syslinux 和 GRUB:
  • Syslinux 是一个启动加载器集合,可以从硬盘、光盘或通过 PXE 的网络引导启动系统。支持的文件系统包括 FAT,ext2,ext3,ext4 和非压缩单设备 Btrfs 文件系统。
  • GRUB ,即 GRand Unified Bootloader(大一统启动加载器),是一个多重启动加载器,承自 PUPA 项目。今的 GRUB 也被称作 GRUB 2,而 GRUB Legacy 表示 0.9x 版本。
    4 p9 l, R6 A% @0 x; _
对于普通用户来说他们有什么用呢?它可以提供选单选择 Linux 内核版本,此外加载程序使得我们可以向 Linux 内核传递参数。这点很重要,在我的案例中 volumio 就是通过 Syslinux 向内核传递启动参数的。
Syslinux 已经不支持 bios64 位系统了,目前使用 GRUB2 的比较多。由于 volumio 使用的是 Syslinux 我没有对 GRUB 展开研究。
下图是 volumio 的默认 syslinux 配置。
  • 微信图片_20201123210146.png
  • LINUX 命令:指定了当前内核文件为 vmlinuz-3.18.5 版本;
  • INITRD 命令:指定了 initrd 文件为 volumio.initrd(之后修改 initrd 也就是修改这个文件);
  • APPEND 命令:是向内核传递的参数,在下文 initrd 的 init shell 中可以通过 cat /proc/cmdline 读取到。8 ?7 J) l1 M+ q
这里指定了 imgpart,bootpart 的 uuid 用于挂载分区,imgfile 名字用于确定当前真实 root 分区的文件名,还有 loglvevel、USE_KMSG 等参数。
5. 内核:vmlinuz 和 initrd
引导加载程序交棒之后系统进入内核引导阶段。这一步会在内存中运行系统内核和根文件系统。之后根目录下的 init shell 会被调用执行,完成进一步的初始化操作。
5.1 vmlinuz 和 initrd
vmlinuz 是可引导的、压缩的内核。“vm”代表“Virtual Memory”。Linux 能够使用硬盘空间作为虚拟内存,因此得名“vm”。vmlinuz 是可执行的 Linux 内核。
initrd 是“initial ramdisk”的简写。initrd 一般被用来临时的引导硬件到实际内核 vmlinuz 能够接管并继续引导的状态。initrd 字面上的意思就是"boot loader initialized RAM disk",换言之,这是一块特殊的 RAM disk,在载入 Linux kernel 前,由 boot loader 予以初始化,启动过程会优先执行 initrd 的 init 程序,initrd 完成阶段性目标后,kernel 会挂载真正的 root file system ,并执行/sbin/init 程序。
采用这种分离的方式,使得我们有机会在内核引导阶段做一些我们自己的事情。简单读了 volumio.initrd 中的 init shell 发现它至少做了几件事情:
  • 读取 syslinux 传递来的环境变量
  • 根据变量决定是否在屏幕打印日志。USE_KMSG 参数决定
  • 加载各种内核驱动模块
  • 挂载 boot 分区
  • 使用 fdisk 处理磁盘,img 文件写入磁盘后大小不一致,首次启动需要使用 fdisk 命令调整分区大小
  • 挂载一个 imgpart 分区,这个不是真正的 root 分区,这里面的 volumio_current.sqsh 文件才是,这样做的目的是方便系统升级,在系统内替换 imgpart 分区的 volumio_current.sqsh 文件即可完成系统升级。volumio_current.sqsh 文件名也是通过 imgfile 参数决定的。
  • 处理 volumio_current.sqsh 升级问题,发现有新的 volumio.sqsh 文件会重命名旧的,然后将新的重命名 volumio_current.sqsh
  • 使用 overlay 方式结合 volumio_current.sqsh 文件挂载真正的 root 分区。
  • 执行 switch_root 命令,重定向新的根分区并执行/sbin/init 命令。
      z8 z9 S1 f% J1 g. z& X/ H) [' E
5.2 initrd 编辑
由于 linux 内核启动后,之前 ipxe 对应的环境已经退出,因此之前挂载的 iscsi 磁盘也无法访问,需要在 initrd 的 init shell 中重新挂载 iscsi 磁盘。因此我需要在上文的 4 步骤之前挂载 iscsi 磁盘,修改如下:
  • 加载网卡内核驱动
  • 启动网络
  • 启动 iscsi 客户端挂载网络磁盘。
    ) [( w2 ?4 y3 Z  I5 |
可以使用如下方式编辑已经生成好的 initrd 文件。
mount -o loop,offset=1048576 ./wrt/Build/Volumio2.799-2020-09-29-x86.img ./vboot/ //挂载img镜像的boot分区到目录0 O/ a6 n" t3 D: `* J
cp ../vboot/volumio.initrd volumio.initrd.gz //拷贝initrd文件,重命名一下! O/ {- Q  f8 _
gunzip ./volumio.initrd.gz //解压gz文件! X! c% M# p9 y! o# N2 o
cpio -ivmd < volumio.initrd //展开initrd文件,在当前目录就可以看到整个rom disk的内容了
7 h: H& o$ j! q" T" [" ~. `4 N4 E
vim init //编辑init shell- Y7 H. f; `' ]# Z; Z4 m8 f
' Y4 s* J9 i" ?; C6 d$ @6 x9 Q
find . | cpio -c -o > ../volumio.initrd.img //重新打包成新的initrd2 q6 N) X3 P* q" Y8 k
gzip volumio.initrd.img
; w" ~" f5 v5 s. m: V9 f3 ^mv volumio.initrd.img.gz volumio.initrd
, E- {' q' ]8 u( o$ L, a( d
还有另外一种方案,由于 volumio 是开源项目,编译 volumio 的脚本在 github 开源。我可以编辑编译脚本,直接修改 init 之后编译成新的 initrd 文件。
git clone https://github.com/volumio/Build.git! C& P. E" M( w6 y1 G& t, ]
ls -la scripts/initramfs/init-x86
. Q+ E1 N0 @1 Y8 {6 Y4 s; d  ]9 jls -la scripts/x86config.sh' l1 g# R& o% L1 h- T# n
  • x86config.sh 这是编译生成 x86 版本 volumio 镜像的脚本,在这个文件中,我们需要添加命令,使得生成的 initrd 文件中包含 iscsi 客户端
  • init-x86 这个文件是 initrd 文件在系统启动后,需要执行的 init shell 脚本。这里我们需要添加 网卡驱动、初始化 iscsi 客户端。& b4 q9 ]( p4 o3 b# M+ b
首先处理 x86config.sh 脚本,我们需要在 initrd 中添加 iscsi 客户端下图中:193-195 行安装 iscsi 客户端 231-232 行向 initrd 中添加 iscsi 模块
微信图片_20201123210149.png
之后处理 init-x86,在 118 行左右的位置,脚本读取了配置在/proc/cmdline 中的根目录 uuid 并在之后挂载磁盘。这里的 cmdline 就是之前说到的在 syslinux 阶段向内核传递的参数。所以我们要在挂载磁盘前加载网卡驱动、启动网络、启动 iscsi 客户端、挂载 iscsi 磁盘。
微信图片_20201123210152.png
修改如下图:
  • 103 行 加载网卡驱动
  • 104 行 加载 iscsi 内核模块
  • 105 行 加载 iscsi ibft 模块
  • 107-108 行 通过 ibft 配置网络
  • 114-116 行 使用 ibft 配置连接 iscsi 服务器并挂载磁盘7 A$ @1 m" U7 D+ F' E9 Z* _2 }
微信图片_20201123210156.png
这里要说一下 ibft 这是一种将 iscsi 配置信息传递到系统的方式,我们在 iPxe 阶段已经配置网络信息、iscsi 服务器地址、iscsi target 等信息了,这里可以使用 ibft 直接读取并使用。当然你也可以在这里再次手动启用 DHCP,手动初始化 iscsi 客户端。
修改完成后,iscsi 磁盘就可以像正常本地磁盘一样被挂载,之后的操作就和正常硬盘安装一样了,正常启动进入 volumio 系统。
6. init 进程
内核引导阶段完成以后,系统会挂载真实的 root 分区,执行/sbin/init 程序初始化系统环境。这一阶段已经和是否网络启动没有关系了,不过启动原理都研究到现在了就顺便一起看一下吧。
/sbin/init 会首先确定运行级别,这个配置在/etc/inittab 中,一般 Linux 有 7 种运行级别(0-6)。一般来说,0 是关机,1 是单用户模式(也就是维护模式),6 是重启。运行级别 2-5,各个发行版不太一样,对于 Debian 来说,都是同样的多用户模式(也就是正常模式)。确定运行级别后会访问/etc/rcN.d(这里的 N 就是运行级别)。
微信图片_20201123210201.png
这里的文件都采用“字母 S 或 K+两位数字+程序名”的命名方式。其中 S 开头的表示在这个级别需要执行 start 命令,K 开头需要执行 Stop 命令,数字越小越优先执行。系统会依次执行相应的软件和服务,负责用户界面的程序也被启动你就有了 X11 界面,然后是 SSH 服务你就可以使用 ssh 登录。这样系统就完成了启动。
当然啦现在这种方式已经过时了,目前基本使用 systemd 方式用 systemctl 命令管理。篇幅已经很长了,这块有兴趣的同学自己搜索一下。
7. 尾巴
6 j! Y+ b1 M# {1 _
4 F/ i+ J3 a: G, N% Y$ q+ h
# O3 V3 O  K5 [! N/ }# Y& |2 y# d
7.1 其他遇到的问题
syslinux 卡死这个问题前面说到了,挂载 iscsi 磁盘后 ipxe 交棒磁盘引导,但是就卡死了。
经过很多的 google 和尝试之后最终发现,我使用了 64 位的 iPxe 引导固件,但是 syslinux 只有 32 位版本导致卡死,更换了 32 位的 iPxe 固件后解决。
可以启动无法关闭这个问题困扰了我很久,系统可以正常启动,但是在关机或者重启时会死机,按键没有任何反应但是系统应该还是活的(大小写灯正常切换)只能强制关机退出。经过排查原因可能是:关机时网络服务会关闭导致网卡关闭,进而导致 iscsi 网盘断开。但是此时系统根分区还没有 umount 导致系统无响应。
我禁用了网络服务的关机关闭,把 K06networking 从 rc0.d 目录中去掉就好了。
Airplay 服务无法找到Volumio 自带 shairport-sync 服务,手机可以通过 airplay 链接 volumio 系统播放音乐,但是在我折腾完以后发现怎么也搜不到。经过排查 shairport-sync 使用 mDns 发布组播告诉局域网内的所有设备自己的地址,使用的是 avahi-daemon 程序。排查日志发现它启动时没有识别到网卡。我猜原因应该是我们的网卡是在内核引导阶段自己拉起的,并不是进入系统后由 networking 服务拉起的,所以 avahi-daemon 无法查找到它对应的 ip。
我没有找到很好的解决方案,还好老爷机还有一块无线网卡,最后使用了无线网卡绑定 shairport-sync 服务。
7.2 最终效果
微信图片_20201123210205.gif
( |$ g6 ^( }2 L# \) y
7.3 总结
总结:为了省掉一块 U 盘,我开始折腾 iscsi 无盘启动没想到这一折腾就是好久,前后研究了好多资料好好的学习了一下 linux 的启动原理。
实际过程并没有文中展现的那么顺利,很多研究的弯路没有在文中一一展现出来。在不同的节点也有很多方案可以选择,比如:iPxe 本可以直接 http 下载 vmlinuz 和 initrd 引导,这样就可以省去 MBR 和 syslinux 引导。但是后来想想都研究了还是整理给大家。再比如 initrd 中 iscsi 客户端的启动和初始化有很多种方式,一开始我都手动初始化网卡,设置 dhcp 和 ip 路由。最后还是觉得太麻烦发现 ibft 的方案最简单,果断选择了它。
水平有限如果发现那里总结的不对欢迎指正。
0 _' d+ C2 E8 [$ L4 V

& M, o2 _+ M7 \, a0 c2 @
收藏 评论0 发布时间:2020-11-23 21:05

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版