
前几天有个做行车记录仪的朋友拿着他的卡找过来说录了一上午的视频还在想覆盖重录却怎么都写不进去——系统弹一个磁盘写保护的提示删文件删不掉新建文件夹也报错。我接过来一看卡是好卡数据也读得出来就是拒绝任何写入。这就是典型的SD卡变成只读。它跟卡坏了读不出来完全是两码事数据还在能读能拷只是所有写操作都被挡在门外。很多人第一反应是格式化结果格式化跑到一半失败卡反倒彻底认不出来了。这份只读修复方法我前后整理过好几轮从普通的手机存储卡、行车记录仪卡到嵌入式板子上跑系统的启动卡我基本都踩过。结论是SD卡的只读不是一个故障而是一类故障。表面症状一模一样背后的原因却差着十万八千里——可能是卡套上一个指甲盖大小的塑料拨片可能是文件系统被系统主动挂成了保护状态也可能是卡里那颗控制器芯片自己把写入通道焊死了。三类原因的修复方式完全相反搞错了顺序本来能救的数据会救不回来。这篇东西写给三类人一类是普通用户卡里存着照片视频只想赶紧把数据拿回来一类是折腾树莓派、开发板、嵌入式设备的玩家卡上跑着系统莫名其妙根目录变成只读还有一类是做存储相关软硬件开发的人需要从文件系统层、驱动层、甚至卡电路的角度理解这件事。全文不推荐任何一键修复神器只讲我自己实测过的判断流程和命令每条命令都说明它在干什么、为什么这么干。1. 先分清楚只读到底从哪来别急着格式化1.1 三种性质完全不同的只读处理方式正好相反物理只读最常见也最容易被忽略。全尺寸SD卡侧面有个拨片开关microSD卡本身没有但市面上大量的microSD卡套上带这个开关。它的原理特别朴素开关拨到LOCK位置时卡套边缘会多出一个凸起压住卡槽里的一个检测弹片读卡器读到这个信号以后就拒绝写入。注意这个开关并不改变卡里的任何数据而且它不是强制生效的——很多便宜的读卡器压根不接这个检测脚开关锁着照样能写反过来有些卡套的开关松了、卡套用久了变形了明明拨在解锁位读卡器也会误判成写保护。我遇到过一次掰了半天卡套的开关都没用最后换个直插的读卡器问题当场消失。逻辑只读是系统层面主动施加的保护。文件系统检测到自身状态异常——比如FAT表损坏、exFAT的卷被标记为脏、分区表有矛盾、上次写入被意外中断——操作系统会自动把它挂载成只读防止在结构已经乱掉的情况下继续写把情况搞得更糟。Windows、macOS、Linux 都会这么做只是表现不一样。这种只读是可逆的把文件系统的错误修掉或者把脏位清掉就能恢复正常写入。固件只读最麻烦。SD卡内部其实是一颗控制器加一片NAND闪存控制器跑着自己的固件负责磨损均衡、坏块管理、地址映射。当它发现坏块数量超过备用块余量、或者映射表读不出来了、或者被反复断电搞坏了FTL闪存转换层表它就会把自己切换到一个仅供读取的状态让你还能把数据读出来但不再接受任何写入。这种状态基本不可逆属于卡的临终状态。有意思的是很多控制器进入这个状态后还会主动把容量改报成一个很小的值或者报0容量这是它在内部做保护时暴露出来的副作用。1.2 为什么我坚决反对先格式化试试因为三类只读里有两类是格式化解决不了的而格式化这个动作本身有代价。对逻辑只读的卡格式化确实能修好但前提是数据你已经备份出来了——很多人是在数据还没拷的情况下格式化把文件系统结构彻底重建了一遍原本可能通过修复分区表恢复的目录结构就真没了。对固件只读的卡格式化跑到一半会因为写失败中断留下一个半残的文件系统比原来更难救。更要紧的是每一次向濒临失效的卡写入都在消耗它最后的可用块。我一般的顺序是先判断是哪一类再决定要不要写入写入之前一定先做只读镜像备份。下面这张分诊表是我自己整理出来贴在工位上的症状对得上哪一行就往对应方向走。典型症状大概率原因该走的方向提示磁盘已写保护换个读卡器就好了卡套开关或读卡器检测脚物理层检查拨片、换卡套能读能拷写入报错Linux下blockdev --setrw成功系统只读标志位软件层清标志位blockdev --setrw报错失败返回 EROFS / EINVAL卡固件自锁抢救数据准备换卡容量显示正常但一个文件都看不到分区表或FAT表损坏镜像备份 分区表重建32GB的卡突然只认到几十MB控制器切换只读并重报容量基本报废优先镜像只有一台电脑上写不进去系统组策略 / 注册表 / 病毒防护换机器验证查系统策略嵌入式设备跑着跑着根目录变只读ext4 错误触发 remount-ro查 dmesg跑 fsck1.3 排查顺序从零成本动作开始一步别跳我给自己定的规矩是从动嘴皮子到动手顺序如下。第一步换读卡器尤其是有卡套的直接换成microSD直插式读卡器这一步能过滤掉大概三成的案例。第二步换电脑或换系统Windows写不进去的卡拿到Linux上试试因为两套系统对只读的判定逻辑不一样Windows可能因为卷脏位直接只读挂载Linux未必。第三步换USB口避开前置面板和无源HUB改用主板后置口供电不稳定的USB口确实会造成间歇性的写失败让人误以为卡写保护了。第四步才是打开终端看只读标志位。第五步无论什么原因只要能读到数据先做镜像。这个顺序看着啰嗦但它省时间。跳过前两步直接上命令的人最后往往在文件系统上折腾半天问题其实是卡套上那个塑料片。2. 动手修复之前先把数据完整捞出来2.1 只读故障时读操作几乎无害写操作在赌运气这是整篇文章最想强调的一条经验。SD卡进入只读以后只要控制器还能响应读取命令把数据完整读一遍的代价极低而且不会让卡的状态变差。反过来任何写操作——格式化、修复、重建分区表、甚至只是改个文件名——都是在赌。卡固件自锁的情况下写入请求会被控制器拒绝听起来没损失但实际上系统会反复重试有些控制器在反复写失败之后会进一步降级响应能力甚至直接掉盘。所以正确的姿势是能读就先读读全了再谈修。对普通人来说最省事的做法是直接在文件管理器里把文件拷出来能拷多少拷多少。但如果卡的文件系统有损坏直接拷贝会在某个坏块处卡住Windows资源管理器可能整个卡死这时候必须上专门做只读镜像的工具。哪怕文件系统看起来是好的只要卡已经有只读症状我也建议做完整镜像因为接下来对卡做的任何操作都可能改变它的状态。2.2 用 ddrescue 做只读镜像参数逐条解释Linux下我的首选是ddrescue它对坏块的处理比dd温和得多而且支持断点续做。先确认设备名这一步千万别省lsblk -o NAME,SIZE,RO,RM,MOUNTPOINT,MODEL看输出里的RO列值为1说明内核已经把这个块设备标成只读MODEL列能帮你确认哪个是读卡器。确认好设备节点以后第一轮先快速扫一遍只读好读的区域遇到读不出来的地方先跳过sudo ddrescue -f -n -b 512 /dev/sdX sdcard.img sdcard.map几个参数值得说清楚。-f是强制对已挂载设备操作虽然我建议先卸载但有时候系统会自动挂载加了这个至少不会中断。-n是第一轮不重试坏区目的是用最快速度把能读的区域全部抓下来先保住大头。-b 512指定扇区大小为512字节SD卡走USB读卡器基本都是512用默认值也行显式写出来更保险。最后那个.map文件是关键它记录哪些区域已经读过、哪些读失败中途断了、卡掉了、机器卡死重启都可以接着来不用从头读。第一轮跑完再针对剩下的坏区做定向重试多给几次机会sudo ddrescue -f -r3 -b 512 /dev/sdX sdcard.img sdcard.map-r3表示对每个坏区重试3次。为什么要分开两轮因为一块卡如果有大面积坏道第一轮就带着重试跑会在每个坏点上耗很久前面好的区域反而一直读不完。先把好区域拿下来再集中啃硬骨头整体时间能省一大半。实测下来一块快挂的行车记录仪卡直接带重试跑要三个多小时两轮制只要四十分钟。Windows下没有原生的 ddrescue可以用HDD Raw Copy Tool做整盘镜像或者用dd for Windows配合管理员权限效果差不多。macOS 上装了 homebrew 以后brew install ddrescue一样能用设备名换成/dev/rdisk2这种原始设备节点速度会比/dev/disk2快很多。注意ddrescue 的源设备写错一位可能把系统盘整个覆盖掉。执行前用lsblk的输出核两遍容量和型号插拔读卡器前后各看一次。2.3 镜像落盘之后所有修复都在镜像上做这是很多教程会略过的关键一步。镜像文件出来以后你面对的是一个普通的磁盘镜像文件可以随意折腾坏了重新拷一份就行。Linux下用losetup加上分区扫描能直接把镜像当设备用sudo losetup -fP sdcard.img lsblk-P会强制内核读取镜像里的分区表自动把各个分区映射成/dev/loop0p1、/dev/loop0p2这样的节点。之后跑fsck、用testdisk找分区、甚至直接挂载读文件都在这上面做。原卡在这期间保持只读不动的状态。只有确认镜像里数据都出来了才考虑要不要对原卡动手。3. 软件层修复从标志位到分区表的完整操作链3.1 先看只读标志位它是判断病情轻重的分水岭Linux把块设备的只读状态放在/sys里读它不用任何权限lsblk -o NAME,RO,SIZE cat /sys/block/sdX/ro sudo blockdev --getro /dev/sdX三条命令都是看同一个东西返回1就是只读。接着尝试解除sudo blockdev --setrw /dev/sdX sudo hdparm -r0 /dev/sdX这里的判断逻辑非常有用我把它当成一个免费的诊断测试。如果--setrw执行成功而且再读/sys/block/sdX/ro变成了0接着能正常写入那说明只读是上层施加的——可能是内核的写保护标志、可能是某个驱动或守护进程设置的卡本身没问题。如果命令直接返回错误比如BLKROSET: Read-only file system或者EINVAL那说明只读是底层报上来的内核想帮你打开也打不开因为卡自己在拒绝。这一个测试就把软件问题和硬件问题分开了成本几乎为零。顺便说个跨领域的对照。只读状态在软件世界里其实是极其常见的设计不是故障数据库里可以专门建只读账号来限制权限前端富文本编辑器会提供只读模式防止误改很多服务会以只读方式挂载配置文件目录。这些只读都是故意的。而这里要处理的只读本质上是被迫的。分清楚这个区别排查的时候心态会稳很多——不要一看到只读就觉得是坏事先问一句这个只读是谁加上的。3.2 Windows 这边diskpart 清标志位和那个容易被忽略的注册表键Windows下先用diskpart看卡自己的属性diskpart list disk select disk 3 attributes disk attributes disk clear readonly exitlist disk的输出一定要用容量核对select disk后面跟的编号选错了下一步可能把系统盘属性改掉。attributes disk会回显当前磁盘是不是只读clear readonly清掉这个属性。这个方法对付系统施加的只读标志很有效但对文件系统损坏导致的只读没用——清完标志位系统一挂载又发现卷是脏的立刻再挂成只读。还有一个坑我踩过有些企业环境或者装过特定安全软件的机器会通过组策略把整个USB存储设备设成只读。检查注册表这个位置reg query HKLM\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies /v WriteProtect如果WriteProtect的值是1那这台机器上所有USB存储设备都写不进去跟你的卡一点关系都没有。删掉这个键或者改成0重启生效。判断方法很简单同一张卡换另一台电脑能写就是机器策略问题。3.3 文件系统修复FAT32、exFAT、NTFS 各有各的招文件系统层的只读通常有两种表现一是卷被标记为脏系统拒绝写入二是FAT表、根目录项这类关键结构损坏系统找不到可靠的位置去写。处理方式按文件系统类型分。Windows下最直接的是chkdskchkdsk X: /f/f是修复错误。加上/r会扫描并尝试恢复坏扇区这个操作非常慢一块32GB的卡在有坏道的情况下能跑好几个小时而且我不建议对已经有只读症状的卡跑/r——它会大量读写可能把卡彻底搞挂。数据已经用 ddrescue 镜像出来了的话就别在原卡上跑/r了。Linux下的对应工具按类型选sudo fsck.vfat -a /dev/sdX1 # FAT32-a 自动修复 sudo fsck.exfat /dev/sdX1 # exFAT需要 exfatprogs sudo ntfsfix /dev/sdX1 # NTFS只能清脏位和重放日志这里要说清楚ntfsfix的定位。它不是Linux 版的 chkdsk它只能做两件事清除 NTFS 卷的脏标志重放日志文件。它不会检查索引、不会修复MFT结构错误。所以 NTFS 的卡在 Linux 下用 ntfsfix 清完脏位拿到 Windows 上可能还是报错最终还是得让 Windows 自己跑 chkdsk。这也是为什么我建议 NTFS 的卡尽量在 Windows 环境下处理。FAT32 有个细节值得记一下它的脏位藏在两个地方FAT表第一项的 bit31 和 BPB 偏移 0x25 的位置。有些工具只清其中一个清完挂载还是只读。fsck.vfat会一起处理。另外 exFAT 的挂载参数里有errorsremount-ro一旦它发现卷不一致会主动把卷切成只读挂载这时候dmesg里会有明确提示dmesg | tail -50看有没有exfat: volume dirty、FAT-fs: Volume was not properly unmounted这类字眼。这些提示是直接指向病因的比瞎猜快得多。3.4 分区表丢失testdisk 找回分区的完整流程如果卡的表现是容量正常但一个文件都看不到多半是分区表或者引导记录出了问题。这时候不要急着格式化先用testdisk来扫。它是只读扫描不会主动改任何东西安全得很。启动以后的关键步骤是选目标盘用容量核对别选错→ 选分区表类型绝大多数SD卡是 Intel/EFI也就是MBR→ 选 Analyse → 选 Quick Search让它扫一遍找到丢失的分区 → 如果扫出来的分区结构正确按P键可以直接列出里面的文件确认能看见你的数据 → 确认无误再选 Write 把分区表写回去。我特别强调先用P看文件列表这一步。很多人扫出分区就直接 Write写回去发现里面的目录结构是残缺的反而把原来的分区表覆盖掉了。先确认文件能列出来、能拷出来再考虑写不写回分区表。而且写回分区表之前镜像一定要已经做好了。3.5 什么情况下重建分区表反而是对的有一种情况我确实会直接重建镜像已经完整做好数据全部确认取出卡又通过了blockdev --setrw的测试说明它没自锁。这时候分区表烂着也没意义直接重建更干净。Linux下用fdisk或者gdisksudo fdisk /dev/sdX # o 新建空的分区表MBR # n 新建分区 # t 改类型FAT32 用 bLinux 用 83 # w 写入写完别忘了重新格式化分区sudo mkfs.vfat -F 32 -n SDCARD /dev/sdX1重建之前多问自己一遍卡真的没自锁吗如果mkfs跑到一半报 I/O error 或者卡直接掉盘那说明卡已经不行了这时候别再反复重试回到镜像抢救的路线上去。4. 嵌入式场景STM32、FatFs 和 Zynq 平台上的只读是另一套逻辑4.1 STM32 FatFs挂载成功但写不进去是怎么回事玩STM32的人经常遇到这种情况卡在电脑上好好的接到板子上用 FatFsf_mount返回FR_OKf_open用FA_READ打开也能读但只要用FA_WRITE或者FA_CREATE_ALWAYS就返回FR_DENIED或者干脆失败。这跟PC上的写保护不是一回事得从代码和硬件两个方向查。先看代码。f_open的第二个参数是模式如果只给了FA_READ那这个文件就只能是只读打开后续f_write必然失败。想创建新文件模式里必须带FA_CREATE_ALWAYS或FA_CREATE_NEW。想看卡上还有多少空间用f_getfree读空闲簇数这个操作是只读的在卡出问题时也能返回结果能帮你判断卡到底还能不能正常响应。真正定位问题要往下挖到diskio.c里的disk_write函数看它返回的是RES_ERROR还是RES_WRITE_PROTECTED还是根本没走到写入就返回了错误——前者是通信或卡的问题后者往往是上层判断卡处于写保护状态直接拦下了。再看硬件。有些板子的SD卡座子旁边会引一个写保护检测脚全尺寸卡座有这个结构microSD卡座通常没有。如果原理图上把这个检测脚接到了MCU的某个GPIO而代码里读这个脚判断是否允许写入那一旦这个脚悬空、被下拉、或者读到了错误电平固件就会一直认为卡是写保护的。这种情况下卡在电脑上完全正常只有在这块板子上写不进去。我用万用表量过一次引脚电平才找到原因查了半小时代码问题在硬件上。4.2 SD卡协议里的写保护到底有几层说清楚这个很多现象就通了。SD卡规范里定义了不止一种写保护机制层次不一样。最外层是物理开关只存在于全尺寸SD卡靠卡套的机械结构触发读卡器的检测触点纯机械信号跟卡内部没有任何关系。microSD卡本身没有这个开关市面上带开关的microSD卡套开关就是个塑料片接到普通读卡器上大多数时候根本不生效因为很多读卡器根本不检测。再往下一层是卡内部CSD寄存器里的几个标志位包括临时写保护和永久写保护。临时写保护可以由主机发命令置位和清除掉电或者重新插拔以后状态可能复位。永久写保护一旦被置位并固化卡就再也写不进去了。规范里还定义了一组写保护命令用于按组管理卡内的写保护区域可以对某个地址范围设保护也能读出保护状态。最底下那层就是控制器的自我保护了它不是规范定义的写保护功能而是控制器固件遇到内部故障时的降级策略。表现上跟永久写保护一模一样能读不能写。但原因完全不同前者是有意设置后者是故障自保。搞清楚这几层的区别能省不少时间。一块卡如果blockdev --setrw报错、dmesg里满屏的 mmc 超时错误那基本就是最底下那层了别再研究写保护开关。4.3 Zynq / PetaLinux 平台制作启动卡分区和镜像的实操这部分的场景很具体在 Zynq 平台上跑 PetaLinux需要手工制作一张启动SD卡把 BOOT.BIN、image.ub、boot.scr 和根文件系统放进去。整个过程里最容易出问题的地方就是分区格式、分区大小和只读挂载。PetaLinux 的构建产物默认在images/linux/目录下一次完整构建之后这个目录里会有几个关键文件BOOT.BIN 是包含了 FSBL、bitstream、U-Boot 的启动镜像image.ub 是打包好的内核加设备树加根文件系统boot.scr 是 U-Boot 读取的启动脚本。这三个文件配合起来决定了板子从SD卡启动时的完整流程。制作卡之前先规划分区。我的习惯是分两个区第一个区用 FAT32大小给到 1GB 到 2GB卷标设成 BOOT专门放 BOOT.BIN、image.ub、boot.scr 这些启动文件第二个区用 ext4卷标设成 rootfs放完整的根文件系统。为什么第一个区必须用 FAT32因为 U-Boot 阶段读文件系统的能力有限FAT 是兼容性最好的选择用 ext4 做启动分区大概率读不到。第二个区分大一点根文件系统解压出来通常有几个G留够空间别卡在99%的位置。先用fdisk或者parted分区sudo fdisk /dev/sdX # 新建两个主分区 # 第一分区起始扇区建议从 2048 开始保证对齐 # 写入分区表后执行 sudo partprobe /dev/sdX然后分别格式化卷标一定要设对sudo mkfs.vfat -F 32 -n BOOT /dev/sdX1 sudo mkfs.ext4 -L rootfs /dev/sdX2接着挂载、拷贝、同步三步一个都不能省sudo mkdir -p /mnt/boot /mnt/rootfs sudo mount /dev/sdX1 /mnt/boot sudo mount /dev/sdX2 /mnt/rootfs sudo cp images/linux/BOOT.BIN /mnt/boot/ sudo cp images/linux/image.ub /mnt/boot/ sudo cp images/linux/boot.scr /mnt/boot/ sudo tar -xpf rootfs.tar.gz -C /mnt/rootfs syncsync这一条经常被忽略。拷贝完直接拔卡缓冲区里的数据还没落盘分区结构可能损坏下次插上就变成只读了——而且是文件系统损坏引发的逻辑只读不是卡的毛病。我自己踩过一次拷完 BOOT.BIN 直接拔插到板子上 U-Boot 报读不到文件卡插回电脑一看卷脏了。加一个sync或者老老实实umount以后再拔。如果卡是之前被写过、需要重新分区的分区表被占用导致fdisk写不进去先清一下头几百个扇区。这一步只做在确认要重建的卡上sudo dd if/dev/zero of/dev/sdX bs1M count8 statusprogress4.4 板子上跑着跑着根目录变只读fstab 和 ext4 的错误策略嵌入式设备跑一段时间突然写不进去报Read-only file system这个现象太常见了八成不是卡的问题而是 ext4 的错误处理策略触发的。ext4 在挂载时有几种错误应对方式默认的行为是errorsremount-ro——一旦检测到文件系统错误立刻把分区重新挂载成只读防止错误扩散。这个设计对系统来说是保护对使用者来说就是设备忽然变成只读。排查的第一步是看内核日志它会告诉你原因dmesg | grep -iE remount|read-only|EXT4-fs error|I/O error如果看到EXT4-fs error ... remounting filesystem read-only那就是这条路。第二步看当前的挂载参数mount | grep / cat /proc/cmdline/proc/cmdline里如果带ro那说明从内核启动那一刻根分区就是只读挂载的这属于设计如此不是故障。有些产品为了防掉电损坏故意让根文件系统只读挂载运行时的写入重定向到 tmpfs 或者 overlay 层这种就完全不用修。/etc/fstab里也要看一眼。如果某一行的挂载选项里写了ro对应的分区就是只读挂载改成rw或者defaults再重启。有些镜像出厂时就是这么配的不是出错。真正的故障是 ext4 检测到错误主动降级。这时候要做的是把系统停下来卸载分区跑 fsck 修复sudo umount /dev/mmcblk0p2 sudo fsck.ext4 -y /dev/mmcblk0p2-y表示对所有询问自动回答是无人值守场景很方便。修完再挂载回来。如果同一块分区反复触发只读那要考虑是不是块设备本身在报 I/O 错误查dmesg | grep -iE mmc0|mmcblk cat /sys/block/mmcblk0/rommcblk0的ro值为1说明只读是块设备层报上来的不是文件系统层。这时候就要往硬件和卡的寿命方向查了。还有一类容易被忽视的场景在虚拟机里直通USB读卡器。如果宿主机已经把这张卡自动挂载了再把它直通给虚拟机虚拟机里看到的就是一个已经被占用的设备往往只能只读挂载或者干脆挂载失败。正确的做法是先在宿主机上umount确认没有任何进程占用再执行USB直通虚拟机里重新挂载。我折腾虚拟机的存储直通时被这个问题误导过好几次。5. 硬件和寿命维度什么时候这块卡真的该退休了5.1 控制器自锁的触发条件比想象中挑剔SD卡内部的控制器固件有一套自己的健康判断逻辑不同厂商的阈值不一样但触发条件大体集中在几个方面。一是坏块数量超过了预留的备用块池控制器没有可用块来做替换了。二是FTL映射表出现了无法恢复的读取错误这块表记录着逻辑地址到物理块的对应关系它一坏控制器就不知道新数据该往哪写。三是闪存磨损度接近或超过设计寿命上限写放大严重的场景下一张卡可能几百个擦写周期就出现大面积坏块。四是被反复意外断电搞乱写入过程中断导致映射表处于不一致状态。这四种情况里前三种基本宣判死刑第四种有时候可以通过让卡完整体验一次上电初始化的过程来缓解。有说法是把卡插在读卡器上通电放置一段时间不要动让控制器自己把内部整理做完有时候能恢复一部分功能。我试过两三次只成功过一次成功率不高但成本也低可以当成最后的尝试。5.2 判断卡是不是真的不行了四条证据不用专业设备普通用户也能做出判断。第一条换读卡器、换电脑、换系统都写不进去症状完全一致。第二条blockdev --setrw返回失败或者返回成功之后立刻又变回只读反复无常。第三条容量显示异常比如标称32GB的卡只认到几十MB、几百MB或者显示成0字节。第四条dmesg里持续出现 mmc 相关的错误比如超时、CRC校验失败、命令响应异常这类。四条里凑够两条以上基本可以认定是卡本身的问题。这里有个反直觉的点值得说卡变成只读其实是它在帮你。真正糟糕的故障是卡直接不认、完全没反应那种情况连数据都读不出来。只读状态好歹给你留了把数据拷出来的窗口期所以我一直劝人发现只读以后第一件事是备份而不是修复。修复的优先级永远排在备份后面。5.3 SD卡电路和读卡器为什么便宜读卡器总背锅SD卡的接口信号里数据线、命令线、时钟线都对时序和电平敏感。走SDIO模式时几根数据线并行传输走SPI模式时MOSI、MISO、CLK、CS四根线通常还需要在数据线和命令线上加合适的上拉电阻保证空闲状态电平稳定。这些细节在板子设计上如果处理不干净表现出的症状就是间歇性的读写失败、CRC错误、甚至被误判为写保护。对普通用户影响最大的其实是供电。USB前置面板、无源HUB、延长线这些地方的供电质量和稳定性都靠不住。SD卡在写入瞬间的电流峰值比读取时高不少供电跟不上的时候写入就会失败。我遇到过一个很典型的案例一张卡插在显示器自带的USB口上写不进去插到主板后置USB口立刻正常。所以排查早期一定要换口试试而且要换到主板直出的口不要用HUB。再一个就是卡座本身。用久了弹片氧化、卡座变形、触点接触不良都会导致通信错误。这种问题在读写频繁的设备上特别常见行车记录仪、监控摄像头这类长期插着卡的设备卡座触点磨损很厉害。有时候把卡拔下来用橡皮擦轻轻擦一下金手指再插回去就好了这不是玄学就是触点氧化。5.4 用卡习惯几个能显著延长寿命的做法第一绝不在写入过程中拔卡。行车记录仪、摄像头这类设备拔卡前先断电或者通过系统正常停止录制等设备把缓存刷完。第二在电脑上拔卡前用系统的安全弹出功能别直接拔Windows下直接拔会让FAT卷标记为脏下次挂载就只读。第三需要频繁写入的场景选高耐久型号的卡不要用普通的拍照卡两者的闪存颗粒和控制器策略不一样。第四重要的卡定期做镜像备份别等到出问题才想起来。第五分区对齐尽量从2048扇区开始避免跨擦除块写入造成的读改写放大这个在嵌入式系统卡上尤其有意义因为系统卡是长期反复写入的。6. 一张速查表把上面的流程串起来6.1 症状到处置的对照速查现场表现先查什么命令或动作成功标志弹窗提示磁盘写保护卡套开关、读卡器换卡套、换读卡器不再弹窗只有一台电脑写不进去系统策略、注册表查StorageDevicePolicies其他机器正常Linux下写失败块设备只读标志blockdev --getro返回0设置只读失败报错控制器自锁dmesg查 mmc 错误无错误输出容量正常但无文件分区表损坏testdisk扫描能列出文件容量异常偏小控制器降级立即做镜像数据可读板子上根目录只读ext4 错误策略dmesg、fsck.ext4恢复可写挂载挂载点被配成只读fstab 配置检查挂载选项改为 rw6.2 一套按成本排序的排查链我把自己用的排查链完整写一遍从最便宜的动作开始每一步都有明确的成功判据。第一步换读卡器成功判据是能正常写入失败就进第二步。第二步换电脑判据同上还不行进第三步。第三步换USB口到主板后置判据同上。第四步Linux下读只读标志位并尝试blockdev --setrw能变可写就说明是软件层处理完就能用失败进第五步。第五步做只读镜像这一步的成功判据是镜像里能读出需要的文件只要这一步成功最坏情况也保住了数据。第六步在镜像上用 testdisk 找分区、用 fsck 修文件系统修好以后把数据盘出来。第七步如果原卡确实没自锁setrw能成功重建分区表并格式化。第八步如果确认自锁换卡。这套流程的好处是每一步都在降低不确定性而且前面几步几乎不花时间。我见过太多人直接从第五步甚至第七步开始结果就是在一块已经快报废的卡上反复格式化浪费几个小时。6.3 我踩过的坑逐条列出来第一个坑被卡套开关骗。有次排查了半小时命令最后发现是卡套的LOCK拨片卡在了中间位置。现在我的习惯是遇到写保护第一件事就是用指甲把拨片来回拨几次确认到位或者干脆换个卡套。第二个坑在没备份的情况下跑 chkdsk /r。那块卡本来能读跑了两个小时/r中途卡死拔下来以后再插就完全认不到了。教训就是有只读症状的卡先镜像别扫描。第三个坑diskpart选错盘号。手快选成了系统盘之外的另一个移动硬盘好在那个硬盘没有重要数据。现在我用list disk一定核两遍容量。第四个坑把 ext4 的自动只读当成卡坏了。一块开发板的启动卡反复报只读换了新卡还是同样症状最后发现是掉电导致 ext4 检测到错误把分区重新挂成了只读。跑一遍fsck.ext4就好了卡一点问题都没有。第五个坑拷完文件直接拔卡。制作启动卡的时候cp完 BOOT.BIN 就拔插到板子上读不到启动文件。加了sync以后再也没有出现过。第六个坑用无源HUB。一块卡在HUB上写不进去直接插主板后置口就正常了。这个坑最容易被忽略因为HUB读文件完全没问题只有写入才暴露。6.4 给不同人群的几条落地建议如果你只是想把卡里的照片视频拿出来最省事的路径是换读卡器、换USB口、换个电脑试一遍能读就直接拷出来拷完了这张卡就别再用于存重要东西了可以降级当临时U盘用。如果你是嵌入式玩家卡上跑着系统那要养成镜像的习惯。一张配好的系统卡做好以后立刻用dd或者 ddrescue 做一份完整镜像存起来卡出问题直接换卡写镜像五分钟恢复比排查快一百倍。系统卡的写入量比普通数据卡大得多日志、缓存都在写寿命消耗快备用卡和备用镜像都得有。如果你是做存储相关开发或者从事数据恢复那这套流程里的关键在于分清层级物理层、协议层、文件系统层、驱动层。每层的判断方法我都写在上面了blockdev --setrw那一个测试是分水岭能过就是上层问题过不了就是卡的问题。把这一条刻在脑子里能省掉大量无效排查。最后再分享一个小习惯。我手里所有长期使用的SD卡都会在卡背上贴一小块标签写上第一次使用日期和用途。卡出现只读症状的时候第一件事是看这个日期——如果已经用了三四年又是在监控、记录仪这种持续写入的场景那基本不用纠结直接走数据抢救流程换卡就行修的意义不大。标签这个小动作花不了几秒钟但能帮你少纠结很多次。