Title: ros2 嵌入式程序的交叉编译 —— 镜像文件的制作



关联博文:

- ros2 嵌入式程序的交叉编译

- ros2 嵌入式程序的交叉编译 —— 镜像文件的制作

- ros2 嵌入式程序的交叉编译 —— 基于 Chroot 文件系统隔离


0. 前言

这里涉及镜像文件的制作、瘦身、修复等.
为网上资料汇总, 仅记录备份, 方便查阅.


I. 镜像文件制作

1. 将 SD 卡通过读卡器插入 Linux 电脑

2. 查看 SD 卡对应的设备名

执行命令 lsblksudo fdisk -l,

SD 卡的设备名是sdb (不含数字后缀), 数字后缀 (如sdb1sdb2) 是分区名, 制作镜像需用设备名

3. 卸载 SD 卡分区

umount /dev/sdb1
umount /dev/sdb2

4. 确认已经卸载 SD 卡分区

再次执行lsblk, 若 SD 卡分区的「MOUNTPOINT」为空, 说明卸载成功

5. 用 dd 命令制作镜像

sudo dd if=/dev/sdb of=/home/robot/ubuntu22_ros2_humble.img bs=4M status=progress

- if=/dev/sdb:输入设备 (即 SD 卡的设备名, 必须准确!)

- of=/home/robot/...img:输出镜像文件路径 (替换为你的保存路径, 确保空间足够 !)

- bs=4M:块大小 (4MB,可提升读写速度, 默认 512 字节太慢)

- status=progress:显示实时进度 (否则无任何输出, 易误以为卡住)

等待命令执行完成, 最后显示

dd_img

6. 查看镜像文件信息

fdisk -l ./ubuntu22_ros2_humble.img

显示

Disk ./ubuntu22_ros2_humble.img: 59.49 GiB, 63864569856 bytes, 124735488 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 46F4E464-E70C-B74B-9A6B-C94673B10DA4

Device Start End Sectors Size Type
./ubuntu22_ros2_humble.img1 61440 2158591 2097152 1G Linux extended boo
./ubuntu22_ros2_humble.img2 2158592 124733439 122574848 58.5G Linux filesystem

原始 SD 卡的尺寸是 64 GB, 则镜像的尺寸也是 64 GB.


II. 镜像文件瘦身

1. 下载 PiShrink

PiShrink (https://github.com/Drewsif/PiShrink) 是专门针对树莓派系统镜像压缩的工具, 我们的系统是针对香橙派板卡的, 幸好也可以用.

wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh

2. 增加脚本的执行权限

chmod + ./pishrink.sh

3. 查看使用方法

sudo bash ./pishrink.sh --help

Usage: ./pishrink.sh [-adhnrsvzZ] imagefile.img [newimagefile.img]

-s Don’t expand filesystem when image is booted the first time
-v Be verbose
-n Disable automatic update checking
-r Use advanced filesystem repair option if the normal one fails
-z Compress image after shrinking with gzip
-Z Compress image after shrinking with xz
-a Compress image in parallel using multiple cores
-d Write debug messages in a debug log file

4. 执行镜像文件瘦身

sudo bash ./pishrink.sh -v ubuntu22_ros2_humble.img ubuntu22_ros2_humble_shrunk.img

输出显示

shrink

5. 查看瘦身后镜像文件信息

fdisk -l ./ubuntu22_ros2_humble_shrunk.img

显示有错误, 需要修复.

partition error1

III. 镜像文件修复

实际的总扇区数是 40958833 sectors, 而不是124735487 sectors (原始未 shrink 前的数据).

GPT PMBR size mismatch 提示镜像的保护性 MBR(PMBR)记录的磁盘大小与实际 GPT 分区表不一致, 这可能导致系统无法正确识别分区, 需先修复.

1. 用 gdisk 工具打开镜像

gdisk 命令是 Linux 上管理 GPT (GUID 分区表)分区的强大工具

sudo gdisk ./ubuntu22_ros2_humble_shrunk.img

执行过程比较复杂, 需要仔细:

robot@precision-7920-tower:~$ sudo gdisk ./ubuntu22_ros2_humble_shrunk.img
GPT fdisk (gdisk) version 1.0.5

Warning! Disk size is smaller than the main header indicates! Loading
secondary header from the last sector of the disk! You should use 'v' to
verify disk integrity, and perhaps options on the experts' menu to repair
the disk.
Caution: invalid backup GPT header, but valid main header; regenerating
backup header from main header.

Warning! Error 25 reading partition table for CRC check!
Warning! One or more CRCs don't match. You should repair the disk!
Main header: OK
Backup header: ERROR
Main partition table: OK
Backup partition table: ERROR

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: damaged

****************************************************************************
Caution: Found protective or hybrid MBR and corrupt GPT. Using GPT, but disk
verification and recovery are STRONGLY recommended.
****************************************************************************

Command (? for help): d
Partition number (1-2): 2

Command (? for help): n
Partition number (2-128, default 2): 
First sector (2048-124735454, default = 2158592) or {+-}size{KMGTP}: 
Last sector (2158592-124735454, default = 124735454) or {+-}size{KMGTP}: 40958000
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): 
Changed type of partition to 'Linux filesystem'

Command (? for help): x

Expert command (? for help): s
Current partition table size is 128.
Enter new size (4 up, default 128): 32
Caution: The partition table size should officially be 16KB or larger,
which works out to 128 entries. In practice, smaller tables seem to
work with most OSes, but this practice is risky. I'm proceeding with
the resize, but you may want to reconsider this action and undo it.


Expert command (? for help): e
Relocating backup data structures to the end of the disk

Expert command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to ./ubuntu22_ros2_humble_shrunk.img.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.

[说明 1]: 重新创建分区 2,结束扇区再缩小一些 (比如 40958000, 多预留更多空间)

[说明 2]: GPT 分区表的备份区域大小与 “最大分区条目数” 相关 (条目越多, 备份表越大). 默认 128 条目的备份表需要更多空间, 而你的镜像裁剪后容量较小, 导致空间不足. 通过减小条目数 (如 32, 或更小的数值如 16、8, 只要 ≥ 当前分区数 2 即可), 可缩小备份表所需空间, 避免与分区重叠.

[说明 3]: 通过 s 命令将分区表条目数减至 32, 减少了 GPT 备份表的空间占用; 通过 e 命令将备份表重新定位到镜像末尾, 确保与分区 2 无重叠.

2. 再次确认瘦身后镜像文件信息是否完好

fdisk -l ./ubuntu22_ros2_humble_shrunk.img
partition_revised_ok2

3. 挂载镜像

按照 “ros2 嵌入式程序的交叉编译” 中的 “附 I. 镜像挂载脚本实现” 挂载镜像文件就可以.

#!/bin/bash

# auto_mount.sh

IMAGE_FILE="/home/robot/crosscompile_ws/rootfs_image/ubuntu22_ros2_humble_shrunk.img"
MOUNT_POINT="/mnt/embedded_rootfs"

# 检查镜像文件是否存在
if [ ! -f "$IMAGE_FILE" ]; then
    echo "错误: 镜像文件 $IMAGE_FILE 不存在!"
    exit 1
fi

# 创建挂载点(如果不存在)
if [ ! -d "$MOUNT_POINT" ]; then
    echo "创建挂载点目录: $MOUNT_POINT"
    sudo mkdir -p "$MOUNT_POINT"
fi

# 提取第二个分区(Linux filesystem)的起始扇区
# 从fdisk输出中过滤包含"Linux filesystem"的行,然后提取起始扇区数值
START_SECTOR=$(fdisk -l "$IMAGE_FILE" | grep "Linux filesystem" | awk '{print $2}')

if [ -z "$START_SECTOR" ] || ! [[ "$START_SECTOR" =~ ^[0-9]+$ ]]; then
    echo "错误: 无法提取有效的起始扇区!"
    echo "请检查分区是否存在或分区类型是否正确"
    exit 1
fi

# 计算偏移量(扇区大小默认512字节)
SECTOR_SIZE=512
OFFSET=$((START_SECTOR * SECTOR_SIZE))

echo "找到分区: 起始扇区=$START_SECTOR, 扇区大小=$SECTOR_SIZE字节, 偏移量=$OFFSET字节"

# 执行挂载操作
echo "正在挂载镜像到 $MOUNT_POINT..."
sudo mount -o loop,offset=$OFFSET -t ext4 "$IMAGE_FILE" "$MOUNT_POINT"

# 检查挂载是否成功
if [ $? -eq 0 ]; then
    echo "成功挂载镜像到 $MOUNT_POINT"
else
    echo "挂载失败!"
    exit 1
fi
mount

IV. 结论


版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/woyaomaishu2/article/details/152812220?spm=1001.2014.3001.5502
本文作者:wzf@robotics_notes

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐