【免费下载链接】pi-gen
Tool used to create the raspberrypi.org Raspbian images
pi-gen 是树莓派官网用来制作 Raspbian 系统镜像的工具(详见 README.md)。它构建流程中最精妙的「镜像导出」阶段堪称磁盘操作范例:先用truncate切出一个原始.img文件,用fdisk非交互写入双分区表,再用losetup循环设备把分区「挂载」成真实块设备,写满 ext4 根文件系统,最后用zerofree把空闲空间清零给镜像瘦身,再打包压缩。下文沿着真实源码,把这些原理一步步讲清楚。
一、镜像导出在哪里被触发?
build.sh 是整个构建的总调度:
- 按字母序依次执行所有
stage*目录:stage0(debootstrap 引导)→ stage1(可启动的最小系统)→ stage2(Lite)→ stage3(桌面)→ stage4(完整版)→ stage5(Mathematica)。每个阶段产出一个不断长大的rootfs/目录树; - 阶段目录里若存在
EXPORT_IMAGE标记文件,就进入导出队列。例如 stage2/EXPORT_IMAGE 声明IMG_SUFFIX="-lite"产出 Lite 镜像,stage4/EXPORT_IMAGE 后缀为空,产出完整镜像; - 所有阶段结束后,build.sh 把
STAGE_DIR指向 export-image/,把导出脚本当作「特殊阶段」对队列里的每个系统依次执行;若阶段还声明了EXPORT_NOOBS且非 QEMU 模式,会接着跑 export-noobs/ 打包。
所以镜像导出并不神秘——它就是系统搭建完毕后执行的又一个「阶段」。
二、🧱 创建骨架:truncate 与 fdisk 分区
导出阶段的核心脚本是 export-image/prerun.sh,它先于所有子阶段执行。
2.1 镜像尺寸是怎么算出来的
脚本先用du统计/boot目录与整个 rootfs(排除 apt 缓存)的实际字节数,然后:
IMG_SIZE = (boot 大小 + rootfs 大小 + 800MB),向上取整到 4MB 对齐——多出的 800MB 是留给系统日后升级的「增长余量」;- boot 分区大小取
2×/boot 实际内容,为固件与内核更新留足空间; - root 分区起点 = boot 分区末端向上取整到 4MB 边界,再外移 8192 个扇区(4MB)间隙,保证分区对齐整齐。
接着truncate -s按该尺寸创建一个稀疏文件——这就是原始.img,此刻全是零字节、没有任何分区表。
2.2 用 fdisk 非交互写分区表
fdisk -H 255 -S 63采用传统 255 磁头/63 扇区几何,兼容树莓派 Bootloader;再配合 heredoc 管道输入命令,全程无需人工交互:
| 命令 | 含义 |
|---|---|
o | 创建新的 DOS(MBR) 分区表 |
n | 新建主分区 1:起始扇区8192(即 4MB 偏移),大小+2×boot/512扇区 |
t/c | 分区 1 类型设为c(W95 FAT32 LBA),即 boot 分区 |
n | 主分区 2:从对齐后的 root 起始扇区到盘尾,Linux 类型 |
w | 将分区表写入镜像文件 |
最终得到经典的双分区布局:小 FAT32 boot 分区 + 大 ext4 rootfs 分区——和官方镜像烧录进 SD 卡后的布局完全一致。
三、losetup 循环设备:让镜像文件「变成」真实磁盘
分区只是普通文件里的一段字节,要格式化并写入,必须让内核把它们当块设备对待,这正是losetup的职责。
3.1 取出分区字节偏移
export-image/prerun.sh 用parted -s unit b print解析出分区 1、2 的起始字节与长度。
3.2 绑定循环设备
BOOT_DEV=$(losetup --show -f -o "${BOOT_OFFSET}" --sizelimit "${BOOT_LENGTH}" "${IMG_FILE}") ROOT_DEV=$(losetup --show -f -o "${ROOT_OFFSET}" --sizelimit "${ROOT_LENGTH}" "${IMG_FILE}")三个要点:
-f自动挑选/dev/loopN空闲设备;-o指定起始字节偏移,--sizelimit限定长度——每个循环设备精确覆盖一个分区,不多一字节;--show输出设备路径供后续步骤使用。
之后就是熟悉的磁盘操作:
mkdosfs -n boot -F 32把 boot 分区格式化为 FAT32;mkfs.ext4 -L rootfs格式化根分区,并借-O关闭metadata_csum、64bit、huge_file等新特性(见 prerun.sh#L56-L61),保证老旧固件与工具都能读取;mount挂载两个分区,rsync把构建好的 rootfs(排除/boot与 apt 缓存)和 boot 文件分别拷入。
数据写完,导出流程进入若干「精装修」子阶段。
四、写入 PARTUUID:让系统找到自己的分区
镜像里的/etc/fstab与/boot/cmdline.txt中还保留着BOOTDEV、ROOTDEV占位符(见 stage1/01-sys-tweaks/files/fstab)。脚本 export-image/03-set-partuuid/00-run.sh 用dd读取镜像文件第 440 字节处 4 字节的 MBR「磁盘签名」,拼上-01/-02得到两个分区唯一的 PARTUUID,再sed改写两处配置:
BOOTDEV→PARTUUID=<签名>-01(boot 分区)ROOTDEV→PARTUUID=<签名>-02(根分区)
这样系统开机后按「磁盘签名 + 分区号」而非/dev/mmcblk0p1这类固定设备名查找分区,即使 SD 卡枚举顺序变化也依然稳定。
五、🧹 系统清理与 zerofree 瘦身
最后一个子阶段 export-image/04-finalise/01-run.sh 专职「减重」:
- 停止 fake-hwclock 服务,
hardlink -t合并/usr/share/doc下完全相同的文档文件; - 删除 apt 缓存、dpkg 备份、旧日志、图标缓存、machine-id 等「首次开机无用」文件;
- 日志文件截断为零长度,并把版本信息写入
boot/issue.txt与随镜像发布的.info文件。
5.1 为什么 zerofree 能让镜像明显变小
卸载根分区后,脚本对循环设备执行 zerofree:
zerofree 扫描 ext4 文件系统,把所有未写入的自由块清零。
此时镜像文件的原始内容变成:系统文件 + 海量连续零字节。压缩算法(zip、pixz/xz)对连续零数据的压缩比极高,最终打包体积因此远低于分区名义大小——这就是「官方镜像只有几个 GB,而 rootfs 分区却有一千多 MB」的核心技巧。
收尾时 scripts/common 中的unmount_image负责 sync 磁盘、按序卸载挂载点并用losetup -d摘除循环设备;随后按DEPLOY_ZIP开关用zip压缩输出到deploy/目录(susi 分支还支持.img.xz)。
六、📦 导出成果一览
| 阶段 | IMG_SUFFIX | 产物 |
|---|---|---|
| stage2/EXPORT_IMAGE | -lite | Lite 镜像(无桌面环境) |
| stage4/EXPORT_IMAGE | 空 | 完整桌面镜像 |
| stage5/ | 空 | 完整版 + Mathematica |
把烧录好的镜像开机,先看到安装引导画面,随后即得到如下 Raspbian 桌面:
七、关键文件路径速查
- 构建与导出总调度:build.sh
- 创建 img、fdisk 分区、losetup 挂载、rsync 写数据:export-image/prerun.sh
- 镜像内 apt 升级与清缓存:export-image/01-set-sources/01-run.sh
- PARTUUID 替换:export-image/03-set-partuuid/00-run.sh
- 清理、zerofree 瘦身、zip 打包:export-image/04-finalise/01-run.sh
- 通用函数(unmount_image、on_chroot 等):scripts/common
- 构建依赖工具清单:depends
全流程回顾
truncate 创建 img → fdisk 双分区 → parted 解析偏移 → losetup 绑定循环设备 → mkdosfs / mkfs.ext4 → rsync 写入数据 → chroot 内 apt 升级 → 改写 PARTUUID → 系统清理 →zerofree 清零空闲空间→ 摘除循环设备 → zip/pixz 压缩输出至 deploy/
十步走下来,一个「裸目录」就变成了可直接烧录、可引导的系统镜像——这就是「树莓派镜像到底是怎么做出来的」的完整答案。
【免费下载链接】pi-gen
Tool used to create the raspberrypi.org Raspbian images
相关推荐
Borg 磁盘镜像备份实战:从整盘归档到瘦身还原的完整指南
Borg 磁盘镜像备份实战:从整盘归档到瘦身还原的完整指南 导读 本文讲解如何用 Borg(Deduplicating archiver)对整个物理磁盘、分区乃
运维存储AList Docker镜像体积优化实战:从1.2GB瘦身到300MB的完整指南
AList Docker镜像体积优化实战:从1.2GB瘦身到300MB的完整指南 AList作为一款功能强大的云存储聚合工具,其Docker镜像的体积优化一直是
后端文件存储1 小时访谈剪出 3 条短视频:「文本标记剪视频」上手实录
1 小时访谈剪出 3 条短视频:「文本标记剪视频」上手实录 周五下午,你拿到一份 1 小时的访谈录像,周一上午前要交出 3 条约 1 分钟的成片。以前这事得打开
人工智能语音音视频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考