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

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

[复制链接]
gaosmile 发布时间:2020-11-23 21:05
0. 故事的开始4 `4 Y( j" U# v! q
8 w% D7 q$ P; ]
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 程序
  • 进入用户界面
    6 x9 h4 c2 g* u  D- S$ [) y% h
微信图片_20201123210055.png
由于我需要从网络启动,过程会变得复杂一些,主要变化如下
  • 在 MBR 引导前,需要执行一系列的 PXE 流程,目的是挂载 iscsi 磁盘。
  • 在加载 linux 内核后,由于之前 iPXE 固件已经退出,还需要再次挂载 iscsi 磁盘。
    + |% T% @) J# e! O
微信图片_20201123210059.png
% r2 x/ |9 p) U, e0 y
% A7 c6 u* ~" V8 Y$ j
1 y; C2 _- ~& c$ k# Z: E
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 9 K1 c! Q; M. ?+ K* Q* U8 c+ k6 k

9 m3 s3 w0 p9 n0 X/ S! N& R' O( [

3 X: b" a5 W: n* s( q' J1.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 应用的配置  E, ]( q7 F/ |
2. PXE
回到我的 BIOS 老爷机,上电自检完成后 BIOS 按照设置的启动顺序应该交棒磁盘,但是 但是 但是 这个机器没有硬盘,也没有插入 U 盘,找不到任何启动设备的 BIOS 将控制权交给了网卡,BIOS 光荣退场进入了 PXE 阶段。
预启动执行环境(Preboot eXecution Environment,PXE,也被称为预执行环境)提供了一种使用网络接口启动计算机的机制。这种机制让计算机的启动可以不依赖本地数据存储设备(如硬盘)或本地已安装的操作系统。
微信图片_20201123210114.png 4 C6 F9 q6 \; N) i& n
) }& j# _! D, V6 h" \5 f# i/ M

6 _! G9 s1 h9 N7 i9 k- m$ u( Y2.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 会加载启动文件,之后根据配置执行动作。这里有多重方案进行下一步操作。
    - F( s, Y2 X% h& s* E8 x' Z
    • 可以直接通过 Http 协议获取 Linux kernel 和 ramdisk 然后启动
    • 或者加载一块 iscsi 磁盘,将 linux kernel 和 ramdisk 等信息放在 iscsi 磁盘中,走正常磁盘引导。我用的是这种方案9 v0 I" \, z0 v& ?6 ~
微信图片_20201123210117.png
, y- ~' l- m: }5 l) b6 r7 @% A' a* w: y( q& Q
- ]( x, v8 B( e1 Q% M
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 位,导致卡死的问题。
    3 m0 O+ n" f1 ^& q
使用如下命令编译(更多细节见:https://ipxe.org/appnote/buildtargets):
git clone git://git.ipxe.org/ipxe.git
4 Z) D9 @2 r( D- N- M2 qmake [platform]/[driver].[extension]: C+ ~( S! l8 j- v7 Y8 e
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-efi
    % X; ?: |+ i  V1 E3 f5 M
Driver:主要选择支持的网卡驱动类型,一般选 ipxe(表示所有支持的网卡,但可能导致生成的启动文件过大,如果过大可以酌情选其它)
Boot type:和启动方式、启动介质有关,参考下表:
微信图片_20201123210120.png
编译时添加 EMBED={脚本名称} 可以关联一个启动脚本。推荐一个大佬做好的脚本 http://boot.netboot.xyz/menu.ipxe 可以直接使用。
我最终命令如下:
git clone git://git.ipxe.org/ipxe.git, w* b, f. E7 M, K$ j4 d8 k
cd ./ipxe/src5 U8 h1 R8 `; j; U# p1 r& T4 p
wget http://boot.netboot.xyz/menu.ipxe
+ q' P/ K" p3 t) T6 r# s6 |make bin-i386-pcbios/ipxe.pxe EMBED=menu.ipxe
0 Q( O: V( X0 F0 s" w2 \
完成之后在/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 架构,不同平台的文件名不同)
    0 m: A# H7 w- @
拷贝之前编译好的 ipxe.pxe 和 menu.ipxe 文件到/www/pxe/目录下,并设置网络启动镜像为:ipxe.pxe
配置正确,启动后就可以看到如下选择界面了:
微信图片_20201123210126.png
% p; X7 t; {) {# h5 u8 t6 e! G6 e
! k1 ^3 l3 R+ P" b# E# A% T" @
  W( M) l$ A4 l- \  f) o0 g9 g' j  x
3. 分区: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 字节。
    ' T0 l* R; F9 I+ Q. x! W
微信图片_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 部分
    ' d- |9 e; b0 i: M( G; a
Disk Partition table:这一部分 64 字节大小被均分为 4 份,每份大小 16 字节,每当我们在硬盘上创建出一个新的主分区或者扩展分区时,便会占用 1 个 16 字节的大小用于记录这个分区的相关信息(例如起始和截止柱面位置、分区文件系统类型等等)。这就是为什么 mbr 分区模式最多只能有 4 个主分区的原因。
MBR 的局限:
  • 最多只支持 4 个主分区,超过 4 个就需要使用扩展分区。
  • 磁盘的最大容量只能到 2.2TB1 K6 c7 H( s2 C
如今我家的硬盘都 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 损坏2 g2 b4 r  N/ _. a
3.3 Bootloader 写入
使用 dd 命令结合 hexdump 可以输出 MBR 信息
dd if=~/Desktop/volumio-2.799-2020-07-16-x86.img ibs=512 count=1 | hexdump -C' Y: j" [: `! V! @3 q
微信图片_20201123210142.png
同样的使用 dd 命令可以拷贝 MBR 信息从 img 文件到物理磁盘。(之前我是分分区写入到磁盘的,导致 MBR 信息丢失无法引导)* k6 Q$ W: P' ]0 f% n' v
dd if=~/Desktop/volumio-2.799-2020-07-16-x86.img ibs=512 count=1 of=/dev/sda. M: n0 o& ?( C. r& n2 U
也可以使用下载的 syslinux 中的 mbr.bin 写入
dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/mbr.bin of=/dev/sda //MBR分区表
2 _7 v* ?$ B5 N9 gdd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/gptmbr.bin of=/dev/sda //GPT分区表
2 s3 U9 u3 A( X. a# N: @: H
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 版本。
    - i' L( [7 N# a" A$ f- ^
对于普通用户来说他们有什么用呢?它可以提供选单选择 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 读取到。
    4 w) _& `# a7 q& g/ B( D
这里指定了 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 命令。3 D8 s9 m- a: a' @3 e& c# l
5.2 initrd 编辑
由于 linux 内核启动后,之前 ipxe 对应的环境已经退出,因此之前挂载的 iscsi 磁盘也无法访问,需要在 initrd 的 init shell 中重新挂载 iscsi 磁盘。因此我需要在上文的 4 步骤之前挂载 iscsi 磁盘,修改如下:
  • 加载网卡内核驱动
  • 启动网络
  • 启动 iscsi 客户端挂载网络磁盘。
    8 Z7 w1 ?$ t7 V1 X' _' N
可以使用如下方式编辑已经生成好的 initrd 文件。
mount -o loop,offset=1048576 ./wrt/Build/Volumio2.799-2020-09-29-x86.img ./vboot/ //挂载img镜像的boot分区到目录% ^. y, p  t" K, Q3 I
cp ../vboot/volumio.initrd volumio.initrd.gz //拷贝initrd文件,重命名一下
# u4 p/ ~2 S' q" n! hgunzip ./volumio.initrd.gz //解压gz文件
1 x; q' D( J. Mcpio -ivmd < volumio.initrd //展开initrd文件,在当前目录就可以看到整个rom disk的内容了
7 d5 E& O% _  b5 o0 P( ]
% w, r3 Y: }) Y3 d' Wvim init //编辑init shell" S/ Z! e& D8 B7 Y! P

* T# Y5 |& t2 I' ~# Afind . | cpio -c -o > ../volumio.initrd.img //重新打包成新的initrd+ h# d+ y1 e' q
gzip volumio.initrd.img
, V6 z" P# _% W; Bmv volumio.initrd.img.gz volumio.initrd
" _* N: j' ~# T6 v6 G' q( W& {& b2 J
还有另外一种方案,由于 volumio 是开源项目,编译 volumio 的脚本在 github 开源。我可以编辑编译脚本,直接修改 init 之后编译成新的 initrd 文件。
git clone https://github.com/volumio/Build.git/ P, c+ V1 y, K) t
ls -la scripts/initramfs/init-x86
6 E" U5 r) b1 Als -la scripts/x86config.sh: i2 @) p) s1 V" e3 V# t
  • x86config.sh 这是编译生成 x86 版本 volumio 镜像的脚本,在这个文件中,我们需要添加命令,使得生成的 initrd 文件中包含 iscsi 客户端
  • init-x86 这个文件是 initrd 文件在系统启动后,需要执行的 init shell 脚本。这里我们需要添加 网卡驱动、初始化 iscsi 客户端。
    2 e- M4 W+ J' x) }
首先处理 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 服务器并挂载磁盘$ e8 R: H; t; g5 F5 Y& h! E9 }
微信图片_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. 尾巴$ N# R# J, }* A; k9 o" M

- ]+ k: i7 B: J2 [- d8 d: S- h
- e* d1 z; f6 I  |3 V$ ^0 _
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
3 `8 P6 V+ J6 S  H8 W6 z3 Z+ d4 Z
7.3 总结
总结:为了省掉一块 U 盘,我开始折腾 iscsi 无盘启动没想到这一折腾就是好久,前后研究了好多资料好好的学习了一下 linux 的启动原理。
实际过程并没有文中展现的那么顺利,很多研究的弯路没有在文中一一展现出来。在不同的节点也有很多方案可以选择,比如:iPxe 本可以直接 http 下载 vmlinuz 和 initrd 引导,这样就可以省去 MBR 和 syslinux 引导。但是后来想想都研究了还是整理给大家。再比如 initrd 中 iscsi 客户端的启动和初始化有很多种方式,一开始我都手动初始化网卡,设置 dhcp 和 ip 路由。最后还是觉得太麻烦发现 ibft 的方案最简单,果断选择了它。
水平有限如果发现那里总结的不对欢迎指正。

& a6 ]) l8 }, I" u0 w
# i% C; Z7 P2 g& f$ Z& ~( w
收藏 评论0 发布时间:2020-11-23 21:05

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版