嵌入式Linux开发——烧写你的镜像:存储介质基础 - 先分清 SD、eMMC 和块设备
嵌入式Linux开发——烧写你的镜像存储介质基础 - 先分清 SD、eMMC 和块设备仓库已经开源所有教程主线内核移植跑新版本imx-linux/uboot都在这里或者一起来尝试跑7.0的Linux欢迎各位大佬观摩喜欢的话点个⭐仓库地址https://github.com/Awesome-Embedded-Learning-Studio/imx-forge静态网页https://awesome-embedded-learning-studio.github.io/imx-forge/好像不少人的确对这块很困惑笔者刚好IMX6ULL的项目完成了最小的一次闭环所以这里同时展开这方面的教程。前言别急着烧先认清“盘”很多人第一次看到镜像烧录教程时卡住的地方不是命令本身。命令其实就那么几条lsblk、dd、sync或者 U-Boot 里的mmc list、mmc part。但是我们有时候还是会难以理解烧录过程重出现的问题。随意一些例子SD 卡是什么你很清楚这是一个存储设备eMMC 又是什么你很清楚这是一个存储设备但是怎么正点原子或者一些厂商告诉你你要用mfgtools了怎么跟SD卡的不太一样/dev/sdb 和 /dev/sdb1 有什么区别U-Boot 里的 mmc 0 为什么到了 Linux 里又变成 /dev/mmcblk0如果这些概念没分清楚后面看到“把完整镜像写入整盘设备”这句话就很容易只记住dd却不知道为什么of不能写成分区。所以这一章先不烧录。我们只做一件事把板子上的存储介质和主机看到的块设备认清楚。SD 卡和 eMMC一个能拔一个焊死在 IMX6ULL 这类板子上最常见的两种启动存储是 SD 卡和 eMMC。SD 卡大家比较熟。它是一张可以拔下来的卡。你可以把它插到读卡器里主机就能像看到一个 U 盘一样看到它。烧录 SD 镜像时主机直接对这张卡写数据。eMMC 则不一样。它是一颗焊在板子上的存储芯片外形上更像板子的一部分。你不能把 eMMC 拔下来插进电脑。想往 eMMC 里写镜像通常要借助板子自己让板子通过 USB 暂时把 eMMC 暴露给主机。这也就是我们说的UMS传递烧录。后面讲 UUU UMS 的时候本质上就是在解决“eMMC 不能拔下来”这个问题。块设备是什么Linux 里把磁盘、U 盘、SD 卡、通过 UMS 暴露出来的 eMMC 这类东西都看成块设备。所谓块设备可以简单理解成一块可以按扇区读写的存储空间。它不像普通文件那样以“文件名”为第一视角而是以“第几个字节、第几个扇区”为第一视角。在主机上看块设备最常用的是lsblk你可能会看到这样的输出sdb 8:16 1 29.7G 0 disk ├─sdb1 8:17 1 64M 0 part └─sdb2 8:18 1 512M 0 part这里先解释一下“分区”。一整块盘可以被切成几段相对独立的区域每一段就叫一个分区。你可以把它想成一本厚笔记本整本笔记本是sdb前面几十页专门放启动文件后面几百页专门放根文件系统。每一段页码范围就是一个分区。Linux 不会只给整本笔记本起名字它也会给每个分区起名字。所以lsblk里TYPE为disk的是整盘TYPE为part的就是分区。这里sdb是整盘设备sdb1和sdb2是这块盘上的两个分区。换成路径就是/dev/sdb - 整张盘 /dev/sdb1 - 第 1 个分区 /dev/sdb2 - 第 2 个分区这不是名字长短的问题而是层级不同。整盘设备和分区设备完整镜像必须写到整盘设备。这句话很重要值得单独放一遍完整镜像写整盘不写分区。为什么因为我们生成的.img不是一个“boot 分区文件系统”也不是一个“rootfs 文件系统”。它是一整块盘的字节布局里面已经包含raw U-Boot 区域 MBR 分区表 boot 分区 rootfs 分区如果你把它写到/dev/sdb意思是“从整张 SD 卡的第 0 字节开始把整盘布局写进去”。这是对的。如果你把它写到/dev/sdb1意思就变成“把整盘布局塞进第 1 个分区里面”。这样分区表会跑到分区内部raw U-Boot 也不在 ROM Code 期待的位置板子自然很难启动。所以后面看到类似命令时sudoddifout/release-latest/images/imx6ull-aes-sd.imgof/dev/sdXbs4M/dev/sdX代表的是例子里的整盘设备不是/dev/sdX1。为什么有时是 /dev/sdX有时是 /dev/mmcblk0主机上不同设备会有不同命名。USB 读卡器、U 盘、通过 UMS 暴露出来的设备常见名字是/dev/sdb /dev/sdc /dev/sdd它们的分区通常是/dev/sdb1 /dev/sdb2而板子自己运行 Linux 后SD/eMMC 通常会叫/dev/mmcblk0 /dev/mmcblk1对应分区会多一个p/dev/mmcblk0p1 /dev/mmcblk0p2 /dev/mmcblk1p1 /dev/mmcblk1p2这里的p只是命名格式的一部分。它表示这是mmcblk0这个整盘设备上的第几个分区。所以不要把/dev/sdb1和/dev/mmcblk0p1理解成两套不同规则。它们都在表达整盘设备 分区编号只是设备类型不一样名字长得不一样。U-Boot 的 mmc 0/1 和 Linux 的 /dev/mmcblk0/1还有一个容易绕的地方U-Boot 里的mmc 0、mmc 1和 Linux 里的/dev/mmcblk0、/dev/mmcblk1不是同一个命名系统。U-Boot 在自己的驱动模型里给 MMC 设备编号。Linux 启动后又由 Linux 内核按自己的枚举顺序创建设备名。在当前 IMX-Forge 板卡约定里我们使用这套映射目标介质U-Boot 里Linux 里SDmmc 0/dev/mmcblk0p2eMMCmmc 1/dev/mmcblk1p2这里的/dev/mmcblk0p2和/dev/mmcblk1p2指的是 rootfs 分区也就是第 2 个分区。不过这件事不要盲信。不同板子、不同 U-Boot 配置、不同接线枚举顺序都可能变。教程后面会反复提醒如果你不确定先在 U-Boot 里看mmc list mmc dev 0 mmc part mmc dev 1 mmc part这些命令不会写存储只是观察设备。在主机上怎么观察主机侧最实用的办法是“前后对比”。插入 SD 卡前看一次lsblk插入 SD 卡后再看一次lsblk新增出来的那块disk才是你的 SD 卡。如果进入 UMS 前后对比也一样lsblk让板子进入 UMS 后再执行lsblk新增出来的整盘设备就是板子借给主机的 eMMC。这里最怕的是凭记忆猜/dev/sdb。今天它可能是 SD 卡明天插了另一个 U 盘它就可能变成/dev/sdc。dd不会替你判断对错所以人要先判断。在 U-Boot 里怎么观察U-Boot 里常用这几条mmc list mmc dev 0 mmc part mmc dev 1 mmc partmmc list看 U-Boot 当前识别到了哪些 MMC 设备。mmc dev 0是选择第 0 个 MMC 设备。选择之后再mmc part就能看这个设备上有没有分区表。如果你已经烧了镜像还可以继续看文件ext4ls mmc 0:1 / ext4ls mmc 0:2 /这里mmc 0:1的意思是U-Boot 的第 0 个 MMC 设备上的第 1 个分区这和 Linux 里的/dev/mmcblk0p1很像但仍然要记住它们是两个阶段里的两套名字。UMS 是什么先有个印象UMS 全称可以理解成 USB Mass Storage。这里不用先背术语只要知道它做了什么板子把自己的 eMMC 暂时伪装成一个 USB 存储设备让主机来写。也就是说eMMC 本来焊在板子上主机摸不到。进入 UMS 后主机的lsblk会突然多出一块盘。你对这块新增的整盘设备写镜像数据最终会落到板子的 eMMC 里。后面的 eMMC 烧录章节会详细讲 UUU 怎么把 U-Boot 跑进 RAMU-Boot 又怎么执行ums 0 mmc 1。现在先知道这个目的就够了UUU/UMS 不是另一种镜像格式它只是让主机能够访问板上的 eMMC。小结这一章只讲了一个基础问题镜像到底要写到哪里。先把几个关键词收一下SD 卡可以拔下来用读卡器写。eMMC 焊在板子上通常通过 UUU/UMS 暴露给主机写。/dev/sdX或/dev/mmcblk0是整盘设备。/dev/sdX1或/dev/mmcblk0p1是分区设备。完整.img要写整盘不写分区。U-Boot 的mmc 0/1和 Linux 的/dev/mmcblk0/1是两套命名需要现场确认。下一章我们继续往下拆既然.img是一整块盘那它里面的分区表、boot 分区、rootfs 分区和普通文件到底是什么关系。