导致SD卡变成只读的原因有以下几种:
1. 在读写过程中,突然断电,导致文件系统损坏;
2. 多次热插拔SD卡,导致文件系统损坏;
3. 读写次数过多引起温度变化,导致信号时序发生变化,SD卡内部或芯片内部采样出错,数据读写异常(此为硬件设计缺陷,可考虑添加上拉电阻、增强IO口驱动能力优化)。

原因分析:
在 Linux 系统中,由于相对于内存来说,硬盘的读写数据很慢,为了保证系统效率,在默认情况下某些已经加载到内存中的数据在任务执行过程中将不会直接写回硬盘,而是先暂存在内存中。
用户通常不需要执行sync命令(数据同步写入磁盘),系统会自动执行update或bdflush操作,将缓冲区的数据写入磁盘。
当系统断电或不正常关机时,内存中很可能有数据尚未写回硬盘,此时很容易造成系统文件系统损坏,从而可能造成数据丢失、系统无法正常开机等。

复现步骤:
例如,采用PC端winscp工具拷贝大文件(50MB)到设备端/mnt/media目录过程中,手动断电,进行复现。

修复方法:可采用文件系统监测和修复工具:fsck。fsck不仅可以对文件系统进行扫描,还能修正文件系统的一些问题。
默认情况下如果系统检测到文件系统有错误,会设置文件系统在下次启动的时候执行fsck检测。
可在开机启动脚本中添加如下命令:
fsck.ext3 -p /dev/mmcblk0p6

  1. [~]$ fsck.ext3 -p /dev/mmcblk0p6
  2. /dev/mmcblk0p6 contains a file system with errors, check forced.
  3. /dev/mmcblk0p6: Entry 'LG.ts' in /mnt/media (1793) has deleted/unused inode 9003.  CLEARED.
  4. /dev/mmcblk0p6: ***** REBOOT SYSTEM *****
  5. /dev/mmcblk0p6: 3027/16576 files (0.4% non-contiguous), 393590/600000 blocks

复制代码


验证fsck可以修复文件系统,重启系统后,可恢复正常读写。若是正常可读写的文件系统,fsck不会触发修复处理。
实际尝试修复的该分区大小约600MB,fsck修复过程大约花费两三秒,系统启动过程可接受。
PS:在实际复现过程中,32G SD卡不易损坏,8G SD卡易损坏。建议采用8G旧卡好复现问题。

【附】
mount操作的关键选项noatime
表示在读取、打开、执行文件时都不会修改文件的access time属性,可在一定程度上就降低了系统的IO操作,提高性能。
示例:mount -o ro,noatime,nodev /dev/mmcblk0p6 /var/revert

/etc/fstab
是用来存放文件系统的静态信息的文件。当系统启动的时候,系统会自动地从这个文件读取信息,并且会自动将此文件中指定的文件系统挂载到指定的目录。

  1. [~]$ cat /etc/fstab
  2. # /etc/fstab: static file system information.
  3. #<file system> <mount pt>      <type>      <options>               <dump> <pass>
  4. /dev/root      /               ext2        remount,ro,noatime      0      1
  5. proc           /proc           proc        defaults                0      0
  6. sysfs          /sys            sysfs       defaults                0      0
  7. usbfs          /proc/bus/usb   usbfs       defaults                0      0
  8. # RAMDISKS
  9. tmpfs          /var/run        tmpfs       size=8m,nodev           0      0
  10. tmpfs          /mnt/websess    tmpfs       size=4m,nodev           0      0
  11. tmpfs          /mnt/upload     tmpfs       size=250m,nodev         0      0
  12. tmpfs          /mnt/hisi_mnt   tmpfs       size=4m,nodev           0      0
  13. tmpfs          /mnt/hisi_cache tmpfs       size=4m,nodev           0      0
  14. nodev          /mnt/huge_1GB   hugetlbfs   pagesize=1GB            0      0

复制代码


字段定义:

<file systems> - 要挂载的分区或存储设备.
<dir> - <file systems>的挂载位置。
<type> - 要挂载设备或是分区的文件系统类型,支持许多种不同的文件系统:ext2,ext3, ext4, reiserfs,xfs, jfs, smbfs,iso9660, vfat, ntfs,swap 及 auto。 设置成auto类型,mount 命令会猜测使用的文件系统类型,对 CDROM 和 DVD 等移动设备是非常有用的。
<options> - 挂载时使用的参数,注意有些mount 参数是特定文件系统才有的。一些比较常用的参数有:

     noatime - 不更新文件系统上 inode 访问记录,可以提升性能(参见 atime 参数)。
     defaults - 使用文件系统的默认挂载参数,例如ext4 的默认参数为:rw,suid, dev, exec, auto, nouser,async.
     nodev - 不解析文件系统上的块特殊设备。

<dump> - dump 工具通过它决定何时作备份. dump 会检查其内容,并用数字来决定是否对这个文件系统进行备份。 允许的数字是 0 和 1 。0 表示忽略, 1 则进行备份。大部分的用户是没有安装 dump 的 ,对他们而言 <dump> 应设为 0。
<pass> - fsck 读取 <pass> 的数值来决定需要检查的文件系统的检查顺序。允许的数字是0, 1, 和2。 根目录应当获得最高的优先权 1, 其它所有需要被检查的设备设置为 2. 0 表示设备不会被 fsck 所检查。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐