基于SD卡的嵌入式Linux系统镜像制作
Posted Naisu Xu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于SD卡的嵌入式Linux系统镜像制作相关的知识,希望对你有一定的参考价值。
文章目录
目的
嵌入式Linux在开发过程中对于软件方面通常是 bootloader、linux kernel、rootfs、applications
分开进行处理的,但到了生产阶段这样就不方便了。比较常见的做法是将所有内容整合到一起制作成系统镜像,这样在生产的时候只要烧录系统进行即可。这篇文件将介绍基于SD卡的系统镜像制作方法。
原理
制作系统镜像的原理非常简单: 系统等内容无非就是一堆放在SD卡上的数据,那么只要保持这些数据在SD卡上分布,原模原样拷贝成一个文件,那这个文件就是系统镜像了。使用时只要将该文件原模原样写入到SD卡上就行。
原理就是上面那样,对于SD卡而言想要更好的制作系统镜像了解一下SD卡的数据分布会更加好:
通常嵌入式Linux系统比较常见的会有两个分区: boot分区 和 root分区。
对于SD卡而言通常从头开始的1M空间是预留的,不会用作分区,并且其中最开头的512字节是主引导区,千万不要随意修改其中内容。主引导区后面的(1M - 512)字节空间很多时候会被用来存放 bootloader(uboot) 。当然这个是看芯片的,很多芯片如果从SD卡启动的话,会从SD卡指定地址读取程序并启动,通常这个地址介于 512~1M 之间的。
boot分区通常从1M往后分布,一般不需要很大,并且通常都是FAT32格式的。boot分区用于存放内核镜像、设备树、内核启动参数文件等。有些芯片的 bootloader(uboot) 也是放在这个分区上的。
root分区通常挨着boot分区往后分布,这个分区一般会设置的大一些,分区格式用到也比广泛,比较常见的使用EXT4格式。root分区用于存放根文件系统和用户应用程序等。
根据上面的原理通常制作基于SD卡的嵌入式Linux系统镜像制作可以分为两种方式:
- 从现有SD卡备份
先把所有要用到的内容都烧录到SD卡上,使之可以在设备上正常运行。然后取出SD卡,从头开始备份数据生成镜像文件。 - 从空白文件开始制作
从空白文件开始对其分区,然后导入各部分对应内容来制作系统镜像。
环境准备
下载安装Ubuntu Desktop(这里使用版本为20.04.4):
https://ubuntu.com/download/desktop
安装完成后进行基础环境安装与设置:
sudo apt update
sudo apt install -y build-essential
sudo apt install -y kpartx
sudo apt install -y gparted
以下根据需求安装:
sudo apt install -y openssh-server
如果使用虚拟机的话为了方便可以开启共享粘贴板、共享目录以及桥接网络。
如果是 从现有SD卡备份 ,并且所有数据都是在boot分区和root分区中的话,可以直接在Windows上操作,主要需要用到下面两个软件:
DiskGenius:http://www.diskgenius.cn
Win32 Disk Imager:https://win32diskimager.org/
系统镜像制作
从现有SD卡备份
首先将SD卡插入电脑上,使用 dh -h
命令或是 GParted
工具查看SD卡分区分布:
上面是两个不同的嵌入式Linux设备的SD卡内容分布。
对于第一个图的SD卡而言,在备份前要稍作调整。从图上可以看到该SD卡中rootfs分区占满了SD卡剩余的空间(14.58GiB),但是实际上才使用了(2.50GiB)。这种情况下使用备份方式制作的系统镜像体积会很大。所以需要对该分区大小进行调整。
(注意该操作可能会不可逆的损坏系统!!!)在 GParted
工具中选中rootfs分区,(如已挂载,右键 Unmount
卸载该分区),右键 Resize/Move
调整分区大小,大小根据需要而定,也不能设置的太小,对于上面清明而言设置为5GiB大小基本就够用了。调整大小后需要点击上面的 √
来套用更改。
接下来就可以在终端中通过 dd
命令来备份制作系统镜像了:
# 先将SD卡插入Ubuntu中
# 使用 lsblk 查看SD卡设备号sdX
# 我这里显示为sdb,下面均以此进行说明
# 如果已经分过区了那么Ubuntu可能会自动挂载
# 逐条使用 sudo umount /dev/sdbn 进行卸载
# 比如上面只有两个分区就用 sudo umount /dev/sdb1 和 sudo umount /dev/sdb2
# 创建镜像文件
touch image.bin
# 将SD卡中有用的数据写入到镜像文件中
# 对于上面第一个SD卡而言大小可以设置为如下
# 1M + 4M + 256M(boot) + 5*1024M(rootfs调整后大小) + 2M(多拷贝点,防止不明意外)
# 对于上面第二个SD卡而言大小可以设置为如下
# 1M + 40M(boot) + 160M(rootfs) + 2M(多拷贝点,防止不明意外)
# 将if后设备中数据从头开始拷贝到of后文件中,count表示拷贝大小,单位由bs指定
# 数据比较大会花点时间
sudo dd if=/dev/sdb of=image.bin bs=1M count=203 status=progress
# 系统镜像比较大,可以压缩为zip格式来减少大小
# zip image.zip image.bin
这个方法操作比较简单,不过有时候可能会有问题,特别是前面哪种需要调整分区大小的情况下出现问题的概率会更加频繁些。
如果所有数据都是在boot分区和root分区中的话,可以直接在Windows上操作,使用 DiskGenius 来调整分区大小,使用 Win32 Disk Imager 读取已分配分区来创建系统镜像。
从空白文件开始制作
从空白文件制作主要过程如下:
- 建立一个空文件;
- 作为块设备挂载;
- 进行分区;
- 向各个分区拷贝需要的文件;
- 根据需求向头部添加bootloader;
# 创建镜像文件
touch image.bin
# 向镜像文件写入空数据固定大小
dd if=/dev/zero of=image.bin bs=1M count=235
# 查看可用的设备挂载点
sudo losetup -f
# 我这里显示 /dev/loop13,接下来都以此进行说明
# 将镜像文件挂载到 /dev/loop13
sudo losetup /dev/loop13 image.bin
# 对挂载的设备进行分区
sudo fdisk /dev/loop13
# 下面是我新建的两个分区的输入情况
# n回车 回车(p) 回车(1) 回车(2048) +32M回车 (如果有额外提示则Y回车)
# n回车 回车(p) 回车(2) 回车(67584) +200M回车 (如果有额外提示则Y回车)
# 接着 a回车 1回车 (将分区1设置为可启动)
# 输入 w 回车保存退出,会有点问题提示不用管
# 更新分区表
sudo kpartx -av /dev/loop13
# 格式化分区建立文件系统
sudo mkfs.vfat /dev/mapper/loop13p1 -n boot
sudo mkfs.ext4 /dev/mapper/loop13p2 -L rootfs
# 挂载boot分区
sudo mount /dev/mapper/loop13p1 /mnt/
# 用喜欢的方式向里拷贝内核镜像、设备树、内核启动参数文件等
# sudo rsync -a src/ /mnt/ --progress
# sudo cp -rfp src/* /mnt/
sync
sudo umount /dev/mapper/loop13p1
# 挂载root分区
sudo mount /dev/mapper/loop13p2 /mnt
# 用喜欢的方式向里拷贝根文件系统、用户应用程序等
# sudo rsync -a src/ /mnt/ --progress
# sudo cp -rfp src/* /mnt/
sync
sudo umount /dev/mapper/loop13p2
# 卸载设备
sudo kpartx -d /dev/loop13
sudo losetup -d /dev/loop13
# 如果头部有bootloader,则写入bootloader
# bs=512 seek=1用于跳过头部512字节
# sudo dd if=bootloader.bin of=image.bin bs=512 seek=1 conv=notrunc
# 也可以从现有的SD卡复制bootloader
# sudo dd if=/dev/sdb of=image.bin bs=512 seek=1 count=2047 conv=notrunc
# 注意conv=notrunc选项参数一定不能漏
# 系统镜像比较大,可以压缩为zip格式来减少大小
# zip image.zip image.bin
系统镜像使用
在Linux上可以直接使用 dd 命令将镜像文件写入SD卡中:
# 如果分区已挂载到别的地方先进行卸载
# sudo umount /dev/sdb1
# sudo umount /dev/sdb2
# 解压镜像文件压缩包
# unzip image.zip
# 将镜像文件写入SD卡,写入可能较慢
sudo dd if=image.bin of=/dev/sdb bs=1M
当然我更加推荐使用工具来烧录,这里 推荐使用 BalenaEtcher 工具 ,这个工具支持windos、macos、linux,其官方页面和项目地址分别如下:
https://www.balena.io/etcher/
https://github.com/balena-io/etcher
总结
上面介绍了基于SD卡的嵌入式Linux系统镜像制作,了解原理后其实过程并不复杂。
如果是基于Flash情况,制作镜像的过程也差不多,主要的差异是空间分布的不同,完全可以根据各自的情况来制作。
以上是关于基于SD卡的嵌入式Linux系统镜像制作的主要内容,如果未能解决你的问题,请参考以下文章