我正在为 Raspberry Pi 使用基于 Pi 内核 5.10.92(64 位)的自定义 buildroot Linux 内核。我已将此映像闪存到两个不同制造商的微型 SD 卡上,并将它们安装在定制的 Pi CM4 PCBA 中。
使用几周后,某些 SD 卡变得无法启动。当我将SD卡插入Linux机器并运行时dmesg
,它显示以下内容:
sd 2:0:0:1: [sdd] 61069312 512-byte logical blocks: (31.3 GB/29.1 GiB)
sd 2:0:0:1: [sdd] Write Protect is on
sd 2:0:0:1: [sdd] Mode Sense: 23 00 80 00
sdd: sdd1 sdd2 sdd3 sdd4
需要注意的一些事项: 由于硬件的使用情况,操作系统每 12 小时自动重新启动一次。 U-boot 是 pi 引导加载程序的目标,以启用双分区 (A/B) 故障转移方案。它检查它的环境 ( CONFIG_ENV_IS_IN_MMC=y
), CONFIG_ENV_SIZE=0x4000
, CONFIG_ENV_OFFSET=0x1000000
) 映像布局如下: 前 4 MB 保留给 u-boot 的环境 启动分区 (fat32) Rootfs A (ext4) Rootfs B (ext4) 持久数据分区 (ext4)
当我尝试在另一个 Linux 系统上单独安装每个分区时,引导分区 ( /dev/sdd1
) 以只读方式安装。对于其他三个ext4
分区,dmesg
显示:
EXT4-fs (sdd2): INFO: recovery required on readonly filesystem
EXT4-fs (sdd2): write access unavailable, cannot proceed (try mounting with noload)
即使使用该noload
选项安装,该设备仍被报告为写保护并以只读方式安装,就像 FAT32 启动分区一样。
我试图了解可能导致整个块设备变为只读的原因。目前,我还没有找到在更多 SD 卡上重现此问题的一致方法,因此任何重现此问题的建议将不胜感激。我们还有其他 SD 卡已使用相同时间或更长时间,没有出现任何问题。
答案1
您的 SD 卡中的内存控制器似乎已决定不再允许您向该介质写入数据。
最可能的原因是它耗尽了磨损级别的块:
闪存本质上是一个大型电容器阵列,您可以单独将其保持未充电状态或充电状态。电容器中是否存储电荷表示存储的位。
要给电容器“放电”,您需要更高的电压。
SD 卡由 NAND 型闪存组成,仅支持块擦除操作。这会导致对单个字节的写入操作,如下所示(我有一个更深入的解释这里):
- 将该字节所在的完整块读取到某个 SD 卡内部 RAM 中
- 擦除整个闪存块
- 修改RAM中块内的字节,并且
- 将结果写回Flash中的块
现在的问题是这些擦除/写入周期主动降级记忆细胞。您不能无限频繁地对同一个单元格执行此操作!遗憾的是,文件系统往往就是这样做的。我的文件系统有一个明确的块,其中存储文件的名称、日期和属性,并且我的程序可能会比其他文件位置更频繁地写入特定文件位置。我们强调闪存!
现在,这里有一个简单的技巧可以完成:请注意我们如何删除整个块?到那时,重新使用原始块就没有实际的优势了。任何其他已擦除的块都一样好。因此,我们只使用一个不经常写入的块。然后我们在表中标记这是存储逻辑块的位置。
那磨损均衡大大延长闪存设备的使用寿命。但是:它有其局限性。如果您定期写入大量数据,例如日志、备份、数据库(尤其是那些更新小存储块的数据!无论多小,这都是完整的块更新,除非您缓存它),在某些时候需要执行更多操作写入将导致电容器变得足够“泄漏”(读出电压变得足够不可靠),您将丢失存储的数据。您的 SD 卡控制器很好,可以帮助您避免这种情况 – 写入数据并丢失该数据比知道无法保存数据更糟糕。
您可能想购买新的 SD 卡。展望未来,您可以做几件事:
- 减少写入压力
- 禁用文件系统中的文件访问时间保存
- 不要写入不需要存储的日志
- 随机覆盖/稳定更新存储属于通过 USB 连接的 SSD,而不是系统启动 SD 卡
- 我完全知道您说这是 CM PCBA,因此“只需添加一个 USB 设备”可能比 30 欧元左右的 240 GB 外部 SSD 成本更多。
- 给予内存控制器自由
- 如果这是通过 nvme 或 SATA 连接的 SSD,您可以在 ext4 文件系统上产生可用空间的操作之后,用于
fstrim
告诉闪存控制器 SD 卡上的哪些块可以被视为未使用。这些直接进入准备重复使用的块堆。
- 如果这是通过 nvme 或 SATA 连接的 SSD,您可以在 ext4 文件系统上产生可用空间的操作之后,用于