ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

eMMC与SSD选型避坑指南:从寿命估算到量产烧录的实战经验

eMMC与SSD选型避坑指南:从寿命估算到量产烧录的实战经验 这个项目一开始其实挺不起眼的给一台边缘设备选内置存储方案无非是EMMC和SSD之间二选一。可是真把物料成本、价格、性能、寿命和量产流程全摆到一起时才发现这两种存储的差距远没有名字上看起来那么近。项目里我连续踩了5个坑从寿命估算到fstrim从HS400时序到量产烧录最后连RAID1和虚拟内存这种“软件优化”都来添乱。这篇就把这些坑原原本本写出来包括计算方法、排查命令和最后怎么收场的。如果你也在做工业网关、边缘盒子、开发板量产或者瘦客户机这类固定存储容量的设备选型这篇文章应该能帮你省下几周试错时间。1. 第一个坑拿容量和价格直接对标忘了写入寿命这件事1.1 “eMMC就是便宜版SSD”这个错觉是怎么来的踩坑不是从读datasheet开始的是从采购口头一句“这玩意儿不就是小SSD嘛”开始的。乍一看eMMC和SSD内部都是NAND Flash都遵循类似的读写擦除逻辑容量单位也一样所以很容易在选型表里把它们放到同一列比价。但实际上eMMC和SSD的架构差异非常大。SSD的主控在PCB或者M.2模块上有独立DRAM缓存、多通道并行访问、比较大的预留空间FTL闪存转换层策略可以做得比较激进。eMMC则是把主控和NAND封装在同一颗芯片里主要面向低功耗、低成本场景通道数少通常没有独立缓存FTL策略偏保守连续写入时很多操作是“边写边搬”离散写能力更弱。我习惯用一个类比SSD像独立厨房灶台多、备菜区大忙的时候还能并行处理多个菜eMMC更像公寓里的公共厨房面积有限、设备少一个人炒菜的时候另一个人只能等着。这个结构差异直接决定了选型时不能只看容量和单价否则后面所有坑都会顺着这个错误源头长出来。1.2 寿命不是拍脑袋出来的一个算账的例子我们项目里有个业务模块每天会产生大量日志和中间文件量级在20GB左右。一开始选了一颗64GB的eMMC大家觉得“64GB空间足够写满了还能清理”就没细算寿命。结果实际测试还没跑完一个月用mmc extcsd read /dev/mmcblk0查寿命预估字段已经能看到明显损耗。存储寿命大致的估算公式可以写成这样寿命天数 ≈ (容量GB × 1000 × 标称P/E次数) / (每日业务写入GB × 写放大系数)注意这里有个很容易忽略的点标称P/E次数不等于实际可用寿命。eMMC器件很多时候不标TBW只给Endurance或者Device Life而且写放大系数受文件系统、空闲垃圾回收策略、剩余空间比例影响很大。SSD因为OP空间大、TRIM策略成熟写放大可以控制得比较好eMMC主控策略保守写放大系数经常在1.5到3之间。拿我们的场景套一下64GB eMMC按3D TLC大约1000次P/E计算每天20GB写入写放大取2那就是64 × 1000 / (20 × 2) 1600天看起来大约4.4年好像还凑合。但如果业务量涨到每天40GB这个数字直接腰斩到800天。而且这还没算高温环境下的P/E衰减、固件后台搬移等额外损耗。相比之下如果选一颗128GB的SSD按150TBW算每天20GB写入寿命是150 × 1000 / 20 7500天量级完全不同。1.3 后来我调整了什么踩完这个坑以后我把选型维度从“容量价格”改成了“容量价格寿命随机写温度掉电保护”。具体做法是把日志模块改成“先写内存缓冲再批量落盘”减少小文件反复刷写。把计划中的64GB eMMC换成128GB eMMC不为了省钱卡容量下限。给每片eMMC做人工寿命摸底量产前先测一周持续写入看DEVICE_LIFE_TIME_EST字段是否异常快涨。这里还要纠正一个误区有人觉得“把用户分区划小一点多出来的空间就能当OP用”。eMMC的内部OP是出厂固件静态分配的你在Linux里把分区划小多出来的空间不一定能被主控拿去做垃圾回收和磨损均衡反而可能造成容量浪费。选型阶段就该选足容量而不是靠后期“软OP”自欺欺人。2. 第二个坑以为fstrim是SSD专属eMMC越用越慢却查不出原因2.1 现象持续写入几天后整机响应越来越差项目进入系统联调后我们搭了一个混合读写压力测试每天模拟真实业务写日志、删旧文件、再写新文件。前三天都正常第四天开始发现eMMC设备响应越来越慢创建一个文件有时候要卡一两秒。查dmesg没有任何IO错误iostat显示utilization 100%但业务IOPS并不高明显不是正常业务负载造成的。当时团队里有个同事直接说“eMMC不支持TRIM越用越慢很正常。”这个结论听上去很有道理但它害我们浪费了两天。因为eMMC协议从MMC 4.4时代就引入了类似TRIM的机制eMMC 5.1更是明确支持discard。问题的核心不在“支不支持”而在“Linux到底有没有把discard请求下发到eMMC以及eMMC固件收到之后到底有没有及时回收”。2.2 fstrim会作用到eMMC吗会但要看队列能力和固件行为要验证fstrim是否作用到eMMC第一步是看块设备队列是否支持discardlsblk -D /dev/mmcblk0这条命令会输出DISC-GRANdiscard粒度、DISC-MAX最大discard字节数、DISC-ZERO等字段。如果DISC-MAX不是0说明内核MMC子系统支持向eMMC下发discard指令。然后可以手动执行一次trimfstrim -v /data如果返回类似“/data: 12.3 GiB (132... bytes) trimmed”的结果说明命令确实到了块设备层。但这不代表物理回收已经完成。eMMC内部有FTL和垃圾回收机制fstrim只负责通知主控“这些逻辑块没用了”主控可能只是简单标记真正的回收会放在空闲时间做。我在Linux下反复试过同样一颗eMMC结论很明确fstrim确实能作用到eMMC但效果和SSD上的表现完全不同。SSD主控收到TRIM后通常能较快回收干净eMMC固件则千差万别有的回收很积极有的几乎要等到大量空闲块耗尽才触发GC这时候系统就会表现为“间歇性卡顿”卡顿背后其实是主控在做后台搬移。2.3 实测后的调整手段排查清楚以后我们把调整方案拆成了几个动作不要给eMMC挂载时直接加discard参数。实时discard在部分eMMC固件上会频繁触发后台GC反而增加写放大和延迟。用定时fstrim更可控。systemctl enable --now fstrim.timer把trim频率从默认的每天一次改成每周一次。对eMMC来说频繁trim未必有收益因为固件的回收节奏不一定跟着命令走。日常监控不要只看df容量还要看eMMC健康字段。eMMC 5.0之后提供了寿命预估mmc extcsd read /dev/mmcblk0 | grep -E PRE_EOL_INFO|DEVICE_LIFE_TIME_ESTPRE_EOL_INFO表示预估寿命状态DEVICE_LIFE_TIME_EST是0到10的估计值数值越大越接近寿命终点。它不是精确剩余寿命但至少能让你在设备批量报废前看到预警。顺便提一下网上有人问“Linux怎么查看eMMC内部垃圾回收情况”其实内核没有通用接口能直接看到内部垃圾数量。eMMC是黑盒主控内部的无效块、待回收块不会暴露给操作系统。你能做的只有通过空闲时段的iostat观察是否有非用户触发的写流量或者用fio做前后对比判断GC到底有没有完成。别被“查看内部垃圾”这种说法带偏那不是标准Linux接口能看到的。3. 第三个坑只看标称顺序读写HS400时序和随机4K差点翻车3.1 标称速度再漂亮也得看总线有没有跑上去供应商给的选型表上eMMC标称“读280MB/s写150MB/s”看起来和入门SATA SSD差距不大。结果实机一测板载顺序读只有180MB/s左右4K随机写更是惨不忍睹。问题出在哪里两个一是总线模式没跑对二是很多人根本不知道HS400并不是配置完就能自动生效的。先理一下理论值eMMC 5.1的HS400模式理论带宽约400MB/sSATA SSD大概550MB/sNVMe SSD则是1.5GB/s以上。看起来eMMC离SATA不远但这只是顺序传输的理论天花板实际还要看SoC的MMC控制器、PCB布线、VCCQ电压和tuning结果。我们最初在设备树里确实开了HS400但启动日志里却显示dmesg | grep mmc0 mmc0: new HS200 MMC card at address 0x0001明明代码里开了HS400实际却降级成了HS200性能直接少一半。后来一查是因为主控需要先做tuning而eMMC在PCB上的走线质量不够好tuning失败后自动降级。这也解释了为什么同型号eMMC放在不同板卡上跑出来的速度差异很大。3.2 HS400模式下用示波器实测时序值不值值得。HS400模式和之前的HS200/SDR模式不同它引入了独立的Strobe信号数据、时钟、命令之间的建立保持时间要求更严。单纯看datasheet上的时序参数没用必须上示波器实际抓CLK、CMD、DATA和Strobe的波形测上升沿、下降沿、建立时间、保持时间。我们后来搭了一套简易测试环境用示波器抓HS400模式下eMMC和SoC之间的通信时序发现高温环境下Strobe信号的眼图裕量明显变小。也就是说室温下调通HS400不代表产品在夏天还能稳定跑。最后我做了个比较保守的决定这块板卡用HS200模式牺牲一部分顺序读速度换取长时间高温运行下的稳定性。这比“跑分好看”重要得多。3.3 选型测试不能只跑AS SSD Benchmark很多人在Windows下拿到eMMC设备第一件事就是跑AS SSD Benchmark然后截一张“读XX MB/s写XX MB/s”的图。AS SSD Benchmark确实能快速反映顺序读、顺序写、4K随机IOPS和访问时间但它有几个问题如果eMMC是通过USB转eMMC读卡器接电脑测的结果完全不能代表板载能力因为桥接芯片本身是瓶颈。跑分只测短时间eMMC这种没有散热片、没有主动散热的器件持续读写20分钟后性能很可能会下降而跑分软件看不到这个趋势。4K随机写才是最关键的差异点NUC 11 Essential Kit带64GB eMMC存储版本的机器跑分低是正常的但作为轻办公或下载机其实完全够用选型不该唯跑分论。我后来整理了一个测试矩阵每次选型都照着跑一遍测试场景关注指标推荐工具顺序读MB/sdd / fio --rwread顺序写MB/sfio --rwwrite随机读4K QD32IOPSfio --rwrandread --iodepth32随机写4K QD32IOPSfio --rwrandwrite --iodepth32混合读写70/30延迟、IOPSfio --rwrw --rwmixread70持续读写温度温度曲线、是否降速/sys/class/thermal fio同一个物料在室温、高温、持续读写三种条件下各测一遍比任何宣传页上的标称值都可靠。4. 第四个坑烧录eMMC和克隆SSD完全是两码事量产阶段返工最烧时间4.1 第一次量产把USB转eMMC读卡器当成“大号U盘”方案定型后进入试产我又踩了个大坑。当时为了省事买了几个USB转eMMC读卡器想着直接把eMMC拆下来当U盘写镜像写完装回板子就跑。结果用dd把整盘raw image写进去之后上板压根起不来。后来一查才明白eMMC和SSD虽然是块设备但eMMC内部有比较特殊的硬件分区结构。它通常包含Boot Area Partition 1/2、RPMB分区和UDA用户数据区。很多SoC的启动流程要求bootloader必须写在boot partition里或者写在UDA特定偏移位置直接拿普通读卡器当作U盘整盘拷贝bootloader的位置和格式很容易对不上自然起不了机。SSD整盘克隆很常见因为大部分SSD就是标准块设备EFI分区、GPT表、LVM这些都在同一个线性地址空间里。eMMC则更像“约定好启动姿势的专用盘”每个平台都有自己的启动要求不能拿克隆硬盘的思路直接套。4.2 不同平台的烧录路径差异项目里同时接触过开发板和小主机烧录方式差别很大。如果是全志平台比如香蕉派M64这类板子常见做法是先用SD卡启动Linux再通过mmcblk1设备写eMMC。写bootloader的时候要特别注意boot分区的只读属性echo 0 /sys/block/mmcblk1boot0/force_ro dd ifu-boot-sunxi-with-spl.bin of/dev/mmcblk1boot0 convfsync echo 1 /sys/block/mmcblk1boot0/force_ro这里的mmcblk1boot0是eMMC的Boot Area Partition 1不是SD卡。写错设备轻则白烧重则把SD卡系统搞坏。如果是瑞芯微平台常见用RKDevTool这类量产工具通过USB下载模式烧写eMMC。全志平台也有类似的工具。每个工具对镜像格式的要求不一样有的只认raw image有的能认Android sparse image。sparse image不能直接dd需要先转换比如simg2img system.img system.raw再说Intel NUC 11 Essential Kit带64GB eMMC存储版本的机器。这类产品走UEFI引导eMMC更像是PC内置硬盘安装操作系统可以直接用官方安装介质量产逻辑和普通PC类似。但真要复制到多个设备还是建议先做一次“烧录-校验-上板-启动”的完整冒烟不要烧几百片才发现镜像里某个分区大小不对。4.3 量产阶段的一些经验烧录后不能只看dd退出码要mount起来校验文件哈希最好再上板完整开机一遍。eMMC固件版本可能不同量产时要锁定物料版本。用mmc extcsd read /dev/mmcblk0可以看器件版本信息不同批次混用可能导致启动行为不一样。网上那些“eMMC读写烧录工具下载”的资源要谨慎尽量从原厂或SoC原厂拿工具别随便下第三方改版软件量产工具出错比硬件故障更难排查。如果想在量产前摸底eMMC健康状态可以在Linux下看mmc extcsd read里的寿命字段。内核没有接口直接看内部GC做了什么但通过空闲时段的IO等待和寿命字段变化能反推后台行为是否正常。这个坑最大的教训是存储选型不只是选完芯片就结束烧录、量产、校验流程同样需要提前验证。否则硬件测试全通过一到产线就卡住。5. 第五个坑把RAID1、虚拟内存和TRIM混着调最后根本不知道瓶颈在哪5.1 系统SSD RAID1、业务SSD RAID1看起来稳调起来乱项目后期有一台设备同时做了“系统SSD RAID1、业务SSD RAID1”。两个mdadm软RAID阵列跑起来以后性能表现非常不稳定。一开始怀疑是盘的问题换了两块新盘还是一样。后来单盘裸测速度正常但raid起来后顺序读比单盘还低这才意识到问题出在配置策略上。mdadm软RAID1有几个容易被忽略的点RAID1的镜像同步和位图文件会带来额外IO如果几块盘速度不一致慢盘会拖慢整个阵列。软RAID是否能透传discard要看md层和底层驱动是否支持可以通过cat /sys/block/md0/queue/discard_max_bytes查看。如果返回0说明RAID层没有启用discard这会让SSD或eMMC在长时间使用后内部无效块累积性能逐渐恶化。当一块盘掉线再重建时整盘同步会产生大量读IO业务高峰期重建会明显拖慢应用。对嵌入式设备来说我更不建议对eMMC做RAID1。eMMC本身寿命有限、容量小、板载不可热插拔RAID1带来的“高可用”非常有限。真要提高可靠性我宁可做双份镜像原子更新也就是系统里保留两个根分区升级时切换启动项一旦新版本起不来还能回滚。5.2 SSD虚拟内存设置技巧反而掩盖了真实瓶颈网上有很多“SSD硬盘虚拟内存设置技巧”核心思路是“为了延长SSD寿命把页面文件关掉或者挪到机械盘”。这个做法放到eMMC设备上尤其危险。页面文件不是罪魁祸首。它通常只在物理内存不足时才被频繁使用写入量远没有日志和临时文件那么大。真正关键的是如果你把页面文件关掉机器物理内存又不够系统会频繁触发OOM或者把进程杀掉用户体验比“SSD寿命缩短”糟糕得多。我们的NUC 11 Essential Kit带64GB eMMC版本测试机只有4GB内存Windows下如果把虚拟内存设成“无分页文件”开几个浏览器标签就卡到不能动。正确做法是保持系统管理的页面文件或者设置固定大小比如物理内存的1.5倍。与其动页面文件不如把浏览器缓存、编译缓存、临时目录放到内存盘或外置存储这样既减少了对eMMC的磨损又不影响系统稳定性。5.3 用合理测试把问题拉回存储本身当RAID、TRIM、虚拟内存、缓存策略全搅在一起时性能问题会变得特别难定位。我后来定了一套比较严格的测试流程先把软件层调优全部恢复到默认状态页面文件交给系统管理RAID先拆掉单盘裸测。用fio分别测顺序读、顺序写、随机4K读、随机4K写Windows下可以用AS SSD Benchmark快速看4K-64Thrd IOPS和访问时间但结论要以Linux fio为准。再逐层加回文件系统、挂载参数、RAID、业务程序每一步只改一个变量。用iostat -x 1观察w_await、aqu-sz和%util判断瓶颈到底在CPU、内存还是存储。最后发现我们那台设备的随机写瓶颈根本不在RAID配置而是eMMC自身4K随机写能力弱加上某个业务组件高频刷小文件。把刷盘频率降到1秒一次以后整机IO压力立刻降下来了RAID性能也正常了。这次项目做完我最大的体会是选存储不能只看一张对比表EMMC和SSD的关系不是“大号小号”而是两种定位完全不同的东西。EMMC适合固定容量、固定场景、成本敏感的嵌入式设备SSD适合需要灵活容量、高性能和强运维能力的通用计算。决定方案之前先把写入模型、寿命预算、量产路径和系统调优范围全部过一遍比拿到实机后凭标称速度做决定靠谱得多。
返回列表