上周有位朋友发来消息,说相机里那张64GB的microSD卡突然只能读不能写,删文件弹"介质受写保护",在相机里点格式化也直接报错。这种情况我这些年遇到过太多次了,从行车记录仪、运动相机、树莓派到工控板上的启动卡,SD卡变成只读几乎是所有玩存储的人迟早要撞上的一堵墙。很多人第一反应是"卡坏了,换新的",但实测下来,真正确认已经物理报废的比例不到一半,剩下的大多数都能救回来,甚至有些根本不是卡的问题,是读卡器、系统策略或者挂载参数在作怪。
这篇就按我自己的排查习惯,把SD卡只读的修复方法从头到尾捋一遍。不管你是普通用户、数码玩家,还是天天跟嵌入式板子打交道的开发者,读完应该都能照着一步步定位到自己那一层。核心思路只有一句话:先分层定位,再决定动不动卡里的数据。
1. 先别急着格式化:SD卡"只读"其实是七八种不同的病
1.1 三种典型现象,指向完全不同的故障层
同样是"写不进去",症状细节差别很大,而这些细节恰好是最好的线索。我一般先问三个问题:能不能读文件?能不能格式化?换电脑换读卡器有没有变化?
第一种,文件能正常打开、能复制出来,但写入、删除、重命名全部失败,系统提示"介质受写保护"或"该磁盘有写保护"。这种情况大概率不是卡内部存储介质的问题,而是写保护信号被触发了,来源可能是物理拨片、读卡器、操作系统策略,或者卡控制器里的一个开关位。
第二种,容量显示异常,比如64GB的卡只显示几十MB,或者显示"未格式化""RAW格式",点进去要么提示需要格式化,要么干脆打不开。这通常是分区表或文件系统结构被写坏了,控制器本身还活着,只是它认为这块区域的数据不可信。
第三种,卡插上后电脑能识别盘符,但打开是空的,提示"没有文件",容量却显示占用了不少空间。这不是只读问题,而是目录项或FAT表损坏,文件其实还在,只是索引丢了。这种卡往往也伴随只读,因为系统检测到结构异常后会自动锁成只读,防止进一步破坏。
这三类的处理路径完全不一样。第一种可能五分钟搞定,第三种要上数据恢复工具,硬按第一种的方法去修第三种,很容易把残留的文件索引彻底冲掉。
1.2 一张对照表:从现象直接定位到层级
我把这些年遇到的案例整理成一张对照表,遇到问题时先对号入座,比盲目试工具高效得多。
| 现象 | 最可能的层级 | 第一步该做什么 | 数据风险 |
|---|---|---|---|
| 删改都失败,读取正常,提示写保护 | 物理拨片/读卡器/系统策略 | 换读卡器、查拨片、查注册表 | 极低 |
| 容量正常但全盘只读,换机器依旧 | 控制器只读位或寿命保护 | 命令行确认ro标志位 | 中 |
| 显示RAW、未格式化、容量异常 | 分区表损坏 | 先做整卡镜像 | 高 |
| 有盘符但文件夹为空 | FAT表/目录项损坏 | 立即停止写入,上恢复工具 | 极高 |
| 插入后时有识别时无识别 | 触点氧化或供电不足 | 清洁金手指、换USB口 | 低 |
| 板子上报Read-only file system | 文件系统错误后内核重挂为ro | 查dmesg、跑fsck | 低到中 |
表格里"数据风险"那一栏很关键。风险高的项目,任何修复动作之前都必须先镜像。我见过太多人上来就跑修复工具,结果工具一顿"修复成功",文件反而全没了。
1.3 排查顺序为什么必须从外到内
正确的顺序永远是:物理层、接口层、系统层、分区层、文件系统层、控制器层。原因很朴素——越靠外的环节,检查成本越低、破坏性越小。
换一个读卡器十秒钟,查一次注册表两分钟,而跑一次chkdsk可能要十几分钟并且会改动卡上的数据。如果问题本来出在读卡器上,你却先跑了修复工具,那就是白白冒了一次险。这个顺序不只是在省时间,本质上是在用最小的代价换取最大的信息量:每排除一层,后面需要怀疑的范围就缩小一圈。
2. 最容易被冤枉的两个环节:物理拨片和读卡器
2.1 microSD本身没有拨片,但卡套和读卡器上有
标准SD卡侧面有一个可以上下拨动的小滑块,拨到Lock位置就是写保护。microSD因为体积太小没有这个结构,但它配套的SD卡套上有,很多USB读卡器的插槽里也有一根检测弹片,专门用来读这个滑块的状态。
我遇到过最典型的案例:一张卡在A读卡器上只读,换到B读卡器立刻正常。拆开看,是A读卡器里那根检测弹片变形了,一直处于压迫状态,控制器就认为用户开了写保护。这种情况用软件怎么修都没用,因为从卡的视角看,它就是被明确告知"禁止写入"。
处理办法很简单:找一个确定能写的读卡器交叉验证,或者直接插到手机、平板、相机里试。如果只有某一个读卡器出问题,那答案已经很明显了。另外卡套上的拨片有时候会因为灰尘或磨损卡在半路,拨到另一端再拨回来,往往能解决。
提示:验证写保护拨片最好用两张不同的卡,一张确定可写。如果可写的卡在同一个读卡器上也变只读,那基本可以锁定读卡器或系统策略,而不是卡。
2.2 读卡器"半死"的典型特征
读卡器不是只有好和坏两种状态,中间还有一大片灰色地带。常见表现是:能识别、能读、写入极慢或者直接失败,偶尔还会掉盘再重新枚举。
廉价读卡器在写入时的电流需求比读取高不少,如果USB口供电不足、用了劣质延长线、或者前面板USB口本身电压偏低,写入就会失败。失败次数多了,某些系统会直接把卷挂成只读来保护。这种情况换到主板后置USB口或者带独立供电的HUB上,问题往往就消失了。
还有一类是读卡器主控和某些高速卡不兼容,尤其是UHS-II卡插在只支持UHS-I的老读卡器上,写入协商失败。判断方法很直接:看设备管理器或者dmesg里有没有反复的重新枚举记录。
2.3 Windows的磁盘策略与注册表WriteProtect
Windows有一个不太被注意的设置:存储设备的写保护策略。如果注册表里HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies下的WriteProtect被设成了1,那么所有可移动存储都会被置为只读。这个键有时是被某些安全工具、单位电脑的管控策略或者恶意程序留下的。
检查方法:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies" /v WriteProtect如果返回0x1,把它改成0或者删除整个键,然后重启。要注意的是,有些环境里这个策略是管理员统一下发的,改完之后可能会被重新写回,那就需要找管理员确认,别自己瞎折腾。
另外还有一种情况是磁盘被设成了"只读"属性,这个不是注册表控制的,需要用diskpart处理。
3. 把"只读"定位到具体一层:命令行确认法
3.1 Windows侧:diskpart的attributes命令
图形界面经常只告诉你"写保护",但不说这写保护来自哪里。diskpart能直接看到磁盘属性位。
diskpart list disk select disk 1 attributes disk输出里如果出现当前只读状态: 是,说明这个只读是磁盘层面的属性,可以直接清掉:
attributes disk clear readonly执行完再插拔一次卡。这一步我建议放在换过读卡器之后、跑chkdsk之前,因为它不改动任何数据,是零风险的。
还要确认一下分区有没有被单独设成只读:
list volume select volume 3 attributes volume卷级别的只读用attributes volume clear readonly清除。这两层有时候会同时存在,清完磁盘层还要看卷层。
3.2 Linux侧:/sys/block与dmesg里的写保护标志
Linux下信息更透明。插上卡之后先看内核怎么说:
dmesg | tail -40比较关键的两行是mmcblk0: mmc0:xxxx 60.0 GiB后面有没有跟(ro),以及主机控制器有没有打印"does not support reading read-only switch"。后者表示读卡器和检测弹片之间没协商成功,某些实现会保守地按只读处理。
再直接查标志位:
blockdev --getro /dev/sdX cat /sys/block/sdX/ro返回1就是只读。另外看一下是不是挂载参数的问题:
mount | grep sdX如果选项里有ro,而你想写,可以尝试:
mount -o remount,rw /mnt/sdcard如果remount直接失败并报"I/O error",那基本可以确定是下面一层的文件系统或者硬件在拒绝写入,而不是挂载参数。
3.3 怎么判断是分区表损坏还是控制器硬锁
这两者的表现有时候很像,但处理方式天差地别。我的判断方法是看三条:能不能读分区表、写入时是立即失败还是超时失败、以及能不能被低格工具识别。
如果fdisk -l能正常列出分区,说明分区表还活着,问题在文件系统层。如果连分区表都读不出来,但设备节点存在,用dd往开头写一小段测试数据,立刻返回"Read-only file system"的,多半是设备级只读;如果是长时间卡住然后I/O错误,那更可能是介质本身出现了坏块。
还有一种简单粗暴的验证:换一台完全不同的系统(比如从Windows换到Linux,或者从电脑换到安卓手机),如果到处都只读,那就不用再怀疑系统层了。
4. 文件系统坏死造成的只读假象:chkdsk与fsck实战
4.1 Windows:chkdsk的正确用法与不能做的事
确认物理层和系统层都没问题之后,再看文件系统。Windows下跑:
chkdsk X: /f加/r会顺带扫描坏扇区,对SD卡来说这个操作非常慢,而且会大量读取,我一般先只加/f。跑完之后如果提示"修复了文件系统错误",再插拔看看是否恢复可写。
这里有个坑必须说清楚:chkdsk在修复时可能会把找不到归属的文件塞进FOUND.000文件夹,重命名成FILE0000.CHK之类。这些文件往往就是你原来丢失的照片或日志,别看到陌生文件夹就删。我就吃过一次亏,一张卡修复后照片全没了,后来在FOUND.000里找回来大半,只是文件名全丢,得靠文件头特征重新识别。
另一个要注意的是:如果chkdsk一上来就报告大量坏簇,且修完还是只读,别再反复跑。反复扫描只会加速一张已经濒临失效的卡的死亡。
4.2 Linux:fsck.vfat与exfat的修复流程
Linux下针对不同的文件系统要用不同的工具。相机卡大多是FAT32或exFAT:
sudo umount /dev/sdX1 sudo fsck.vfat -a /dev/sdX1-a是自动修复,-y是全部回答yes。exFAT的话用:
sudo fsck.exfat /dev/sdX1注意命令里的1是分区号,别直接对着整盘/dev/sdX跑fsck,那样会破坏分区表。
如果fsck报出"FATs differ",意思是主备两份FAT表内容不一致,它会问用哪一份。这时候如果卡里有重要数据,我的建议是先镜像再用另一份表做对比,别当场选一个。因为选错了,文件链就彻底乱套了。
修复完之后重新挂载,如果还是只读,看内核日志里是不是有 "FAT-fs: invalid ... " 或者 "remounting filesystem read-only",这类信息能告诉你到底是修好了还是压根没写成。
4.3 分区表和"卡里没文件":别被Windows的盘符骗了
Windows有个毛病:只给可移动磁盘的第一个分区分配盘符。如果你的卡上有多个分区(比如做过启动盘的卡,第一个是FAT32的boot分区,第二个是ext4或者大容量数据分区),Windows只会显示第一个,于是你看到的是"卡里没文件",其实数据在第二个分区里。
这种情况打开磁盘管理就能看到真相。Linux下用lsblk或者fdisk -l更直观。如果分区表本身损坏导致分区全部消失,那就需要testdisk这类工具来重建。testdisk会扫描整块介质,尝试从残留的引导扇区推测分区边界:
sudo testdisk /dev/sdX选Analyse,让它扫描,通常几分钟到几十分钟不等。找到分区后先别急着写入,选中分区按P先看看文件列表能不能列出来,能列出来再保存分区表。
5. 卡自己的控制器锁死:密码锁、寿命保护与低格
5.1 CMD42密码锁:一种被严重低估的只读
SD协议里有一条命令叫CMD42,用来设置和解除卡的密码锁。卡一旦被设了密码,就会进入锁定状态,表现就是全盘只读、无法删除、无法格式化。关键问题是:这个锁是记在卡控制器里的,跟操作系统完全无关,换十台电脑都一样。
哪些情况下会中招?一些相机、行车记录仪、老式MP3播放器提供了"锁定存储卡"的功能,误触之后就锁上了。还有一些低质量的分区工具、格式化工具在异常中断时可能把卡留在锁定状态。更麻烦的是,如果没有密码,这块卡基本就报废了——没有任何通用工具能在不知道密码的前提下解锁,这不是软件能力问题,是协议设计如此。
判断方法:如果在多个系统、多个读卡器上都严格只读,且分区表读取正常,但连低格工具都拒绝写入,可以做一次整盘清零测试。如果清零也失败,就要考虑密码锁的可能。这时候唯一的解法是找到当初设置密码的那台设备,用原设备解锁,或者确认密码。
5.2 写坏块与寿命耗尽的自我保护
另一种常见的硬只读来自卡自身的磨损管理。TLC闪存的寿命是有限的,当控制器发现可用备用块耗尽、或者写入过程中出现无法纠正的错误时,有些方案会主动把整卡切成只读,避免用户继续写入导致数据彻底消失。这其实是一种保护机制,是在告诉你"赶紧把数据搬走"。
这种情况的典型特征:之前有过长时间大量写入、卡变得很慢、有时候出现文件读取错误,然后突然就只读了。这种卡即便用工具强行改回可写,写进去的数据也不可靠,可能过两天就丢了。我个人的处理原则是,确认到这个阶段,只做数据导出,不再做任何写入尝试。
5.3 SD Memory Card Formatter与厂家量产工具
如果排除了密码锁和明显的寿命耗尽,可以试试官方格式化工具。SD Association出的SD Memory Card Formatter对SD卡的处理比系统自带格式化更规范,它会按卡的规范去重建引导区,并且提供了"覆盖格式化"选项(Overwrite format),虽然很慢,但对一些逻辑层面的混乱有效。
操作上有两个细节很多人忽略:一是一定要用管理员权限运行,二是在选项里把"格式化大小调整"(Format Size Adjustment)设为ON,这样能修复一部分容量被错误识别的问题。卡在手机、平板、相机里被别人用"简化版"格式化之后,容量显示异常,用这个选项往往能恢复。
再往下就是各主控厂商的量产工具了,比如群联、慧荣、擎泰这些方案都有对应的MP工具。这类工具的用法因主控而异,需要先用ChipGenius之类的工具读出主控型号,再找匹配的工具。我要提醒的是,量产工具是最后手段,它本质上是重写卡内的映射表,一旦失败,数据就彻底没了。做之前必须整卡镜像,而且要有"卡可能就此报废"的心理准备。
6. 先救数据再修卡:只读窗口其实是最佳抢救期
6.1 为什么只读状态反而是好事
很多人把只读当灾难,我反而认为这是一次机会。只读意味着卡上不会再有新的写入,也就不会再有新的覆盖。对于数据恢复来说,最怕的就是"边丢边写"——文件索引坏了,系统还在后台写日志、生成缩略图,把原来还有救的数据一块块吃掉。
所以正确的心态是:发现只读,第一件事不是想办法解锁,而是尽快把能读出来的东西读出来。只要还能读,数据就还有希望;一旦你强行解锁并开始写入,希望就小了一半。
6.2 ddrescue做整卡镜像的具体步骤
Linux下我最常用的是ddrescue,它比dd聪明的地方在于能记录进度、能跳过坏块、能中断后续传。
sudo apt install gddrescue sudo ddrescue -f -n /dev/sdX card.img card.log第一遍用-n不做重试,快速把好的区域读出来。然后第二遍针对坏区做精细重试:
sudo ddrescue -f -r3 /dev/sdX card.img card.log-r3表示每个坏块重试3次。如果卡有大量物理坏块,可以再加-d直接访问设备。整个过程可能有几十分钟到几小时,耐心等,别中途拔卡。
镜像文件建议放在容量足够的硬盘上,别放在同一张卡或者同一台机器的U盘上。镜像完成之后,所有的修复和分析都在镜像上做,原卡拔下来放好,不再动它。
6.3 镜像之后,修复顺序不能乱
拿到镜像文件之后,处理顺序是:先在镜像上试修复,修复成功并且确认数据完整之后再考虑把内容写回原卡或者新卡。
判断数据是否完整,最直接的办法是看文件数量和目录结构。如果是相机卡,先统计一下DCIM目录下的照片数量和你印象中的是否吻合;如果是记录仪,看看日期连续性有没有断档。别只看"能打开"就以为成功了,我遇到过修复后目录结构完好但后半段文件全是0字节的情况,那就是镜像过程中坏区没读出来。
7. 嵌入式开发里那些"像SD卡坏了"的只读问题
7.1 fstab里的ro参数:板子起来就写不进去
做嵌入式的人遇到的"只读",有很大一部分跟卡一点关系都没有,纯粹是挂载参数写死了。很多产品的rootfs分区为了防掉电损坏,在/etc/fstab里配置成:
/dev/mmcblk0p2 / ext4 ro,noatime 0 1这时候你在系统里改任何文件都会报"Read-only file system",但这不是故障,是设计。要临时写入可以:
mount -o remount,rw /改完记得改回去,否则设备掉电时容易把文件系统写坏。这是很多生产环境的常规做法,新人第一次上手经常被吓一跳,以为卡坏了。
7.2 Zynq/PetaLinux启动卡制作后出现的写保护假象
用Xilinx的PetaLinux流程做启动卡,典型流程是先用petalinux-package --boot生成BOOT.BIN,把image.ub和boot.scr放进FAT32的boot分区,再用SD卡做启动盘。这一步做完之后,很多人发现卡在电脑上写不进去了。
原因通常有两个。一是启动卡分区结构完整,Windows只给第一个FAT分区分配盘符,第二个ext4分区不可见,你看到的"可写空间只有几十MB",误以为卡被写保护了。二是某些写入工具在写IMG镜像之后会把设备重新挂载,如果此时卡还被占用着(比如虚拟机的USB直通没有释放),系统就会把设备锁成只读。
遇到这种情况,先确认设备是不是被虚拟机或者Docker占着,把USB设备从虚拟机里释放出来,再重新插拔。还有一点很多人忽略:写镜像用dd之后必须执行sync,否则缓存没落盘就拔卡,分区表会被写坏,表现出来又是一块"只读卡"。
7.3 STM32+FatFs下写失败的排查清单
MCU端用FatFs操作SD卡,写失败返回FR_DENIED或者FR_WRITE_PROTECTED,排查顺序建议是这样:
- 先确认
f_open的mode参数里带了FA_WRITE,只带FA_READ当然写不了,这个低级错误我犯过不止一次。 - 检查SPI模式下CMD24(单块写)有没有响应,如果卡的写保护开关信号被硬件拉高,CMD24会被拒绝。
- 检查供电,SD卡写入时的峰值电流比读取高很多,3.3V电源如果压降超过一定范围,写入会随机失败。串一个电容在卡座电源脚附近是最省事的改善办法。
- 检查SPI时钟频率,初始化阶段必须降到400kHz以内,正常运行也不要超过主控和卡都能接受的范围。时钟太高时写命令会丢,表现和只读很像。
- 如果是SDIO模式,确认DMA和中断优先级没有冲突,写超时往往表现为"卡被写保护"。
另外提醒一句,FatFs的disk_ioctl需要正确实现CTRL_SYNC,如果f_sync没生效,掉电后文件系统结构会损坏,下一次挂载时就可能被格式化成只读。
8. 让SD卡别再变只读:几条我一直在用的习惯
8.1 拔出前的手势和供电
SD卡出问题,绝大多数跟"拔得不对"有关。读写过程中拔卡,等同于让一块存储设备在写到一半时断电,控制器里的映射表一旦没写完,整卡逻辑就乱了。
我的习惯是:任何设备上拔卡之前,先确保没有读写操作。相机里等存储指示灯熄灭,电脑上先"安全弹出",树莓派上先sync再poweroff。这些动作加起来也就几秒钟,但能省掉后面几个小时的折腾。
供电也是一样。读卡器别插在键盘上的USB口或者没供电的老HUB上,尤其是写入大文件的时候。电压一抖,写入就断,断几次卡就开始自我保护了。
8.2 卡的分工与寿命管理
我的做法是把卡按用途分开:常写入的设备(行车记录仪、监控、树莓派系统盘)用高耐久卡,偶尔导出的设备(相机)用普通卡,两者不混用。记录仪这类设备一天写几十GB,一两个月就能把普通卡的寿命吃掉一大截,用错了卡,坏得特别快。
还有一点是定期检查。每隔一段时间把重要设备里的卡拿出来跑一次chkdsk或者fsck,看看有没有坏簇预警。很多卡在彻底只读之前是有征兆的:写入变慢、偶尔读不出某个文件、容量显示偶尔异常。
8.3 遇到只读卡的标准处理流程
最后把我自己的处理流程固定下来,遇到问题就照着走,不凭感觉:
- 换读卡器和电脑交叉验证,确认是不是卡本身的问题。
- 检查物理拨片、卡套、触点清洁。
- 用diskpart或
blockdev --getro确认只读发生在哪一层,能清的属性先清掉。 - 不用任何软件先尝试写入,如果连写入测试都失败,直接进入镜像流程。
- ddrescue整卡镜像,镜像完成前不做任何修复动作。
- 在镜像上跑chkdsk或fsck,确认数据完整。
- 数据保住了再考虑低格、量产工具或者干脆换新卡。
这套流程救回过我不少卡,也救回过朋友拍了一整天的素材。真正让我印象最深的一次,是一张只读的行车记录仪卡,镜像出来之后发现事故当天的片段完整无损,卡后来确实是报废了,但数据一个没丢。所以在只读这件事上,先救数据、再修卡,永远是性价比最高的选择。
日常还有一个小技巧分享:如果只是临时要把几个文件拷进一张只读的卡,而你又急着用,可以在Linux下用mount -o remount,rw试试,有时候能撑过这一段。但别指望它长久,这只是一种应急手段,卡的底层问题还在,该换还得换。