我可以访问嵌入式 Linux 设备的控制台。该设备有闪存,其中一部分被分区为 FAT 文件系统。
它运行的是linux-2.6.31。
然而,最近我在控制台上看到了这些错误,并且 FAT 文件系统变成了只读。
111109:154925 FAT: Filesystem error (dev loop0)
111109:154925 fat_get_cluster: invalid cluster chain (i_pos 0)
111109:154925 FAT: Filesystem error (dev loop0)
111109:154925 fat_get_cluster: invalid cluster chain (i_pos 0)
我不明白为什么会发生这种情况?根本原因是什么?解决办法是什么?我希望得到答案,告诉我如何在设备上调查此问题的可能根本原因。
答案1
在位和字节级别上实际发生的情况是文件分配表的 4 个字节(或更多)已被0x00
字节覆盖。
我将简要解释一下文件分配表的工作原理。它可以看作一个数组,其值是该数组的索引。因此,如果我们知道文件的第一个簇号是i
,那么下一个簇号是fat[i]
,再下一个簇号是fat[fat[i]]
,依此类推。(这略有简化)。为了表示已到达链的末尾,使用特殊的 EOC 值代替有效的簇号。
要从磁盘读取 FAT 文件,您需要按顺序获取文件存储的簇号。目录条目提供第一个簇号 ( i
)。其余簇号可按照链 等方式找到fat[i]
,fat[fat[i]]
直到遇到 EOC 值。然后只需进行简单的计算,即可从簇号中获取每个簇在磁盘上的位置,将每个簇读入内存并将它们连接起来。
fat_get_cluster: invalid cluster chain
发生错误0x00000000
当找到值时遵循这样的链。这种情况不应该发生。它应该是一个新的有效簇号或 EOC 值。发生这种情况时,无法读取文件的任何内容,因为无法进一步遵循链。(该0x00000000
值用于将簇标记为空闲。簇0
从不用于存储数据,因此不存在歧义)
您的情况可能比较特殊,因为i_pos
给出的是 0。当我收到此消息时,它是一个很大的数字。内核源代码说:
loff_t i_pos; /* on-disk position of directory entry or 0 */
所以 i_pos 不是簇号,而是磁盘上的位置。当它为零时意味着什么,我不知道。
编辑:至于可能的原因,我只能推测,但有以下几种可能性:
- FAT 驱动程序错误。
- 宇宙射线。
- 病毒或其他恶意软件。
- 也许如果两个程序/驱动程序出于某种原因同时写入和读取同一个 FAT,它们可能会互相干扰。不知道是否有可能。
- 在错误的时间硬关机。闪存驱动器必须在写入更改之前将块清零,因此理论上擦除后立即关机会导致此结果。故障保险以防止在大多数驱动器上发生这种情况。
- 用户错误或破坏(例如
dd if=/dev/zero of=/dev/sda1 bs=512 count=1 seek=32
- 不要在家尝试此操作!)
FAT 文件系统驱动程序实际上保持两个 FAT 表处于最新状态以实现冗余,第二个位于就在第一个之后检查它们是否相同可能会为可能发生的情况提供线索。如果它们仅在破坏簇链的值上有所不同,那么我认为以某种形式直接篡改的可能性会更大,因为至少 1 和 3 应该可以“正确”完成这项工作。
不过,在我看来,大多数现代驱动程序可能会将整个 FAT 表保留在 RAM 中,并将更改的部分写回驱动器上的两个副本。因此,即使曾经存在差异,也可能会在正常使用过程中快速且悄无声息地“修复”。请注意,这只是一个有根据的猜测。
最后,如果没有进一步了解情况,很难确切知道,即使有,也可能只是猜测。理想的情况是,如果您可以可靠地重现问题。然后,我会比较“之前”和“之后”的 FAT 表(和 FAT 头),以确切了解更改了什么以及更改了什么,并在更改的位置和内容中寻找提示。
答案2
您的 FAT32 因某种原因已损坏。我的 USB 驱动器经常会出现损坏的 FS,因为我目前正在调试 ARM 平台上的 USB 主机问题。经过测试后,我从台式机(Ubuntu 11.04)发出以下命令:
$ sudo fsck.msdos -aw /dev/sdb1
参考:https://askubuntu.com/questions/31614/how-to-delete-edit-files-from-readonly-filesystem
答案3
您收到的错误无效簇链和文件系统错误清楚地表明这是文件系统错误。
维基百科中关于 FAT 的条目是这样说的:
分区被划分为大小相同的簇,即连续空间的小块。簇大小因所用 FAT 文件系统的类型和分区大小而异,簇大小通常介于 2 kB 和 32 kB 之间。每个文件可能根据其大小占用一个或多个簇;因此,文件由这些簇的链表示(称为单链表)。但是,这些簇不一定在磁盘表面彼此相邻存储,而是通常分散在整个数据区域中。
这文件分配表 (FAT)是映射到分区上每个群集的条目列表。每个条目记录以下五件事之一:
- 链中下一个簇的簇号
- 一个特殊的簇链末端 (EOC) 条目,用于指示链的末端
- 标记坏簇的特殊条目
- 零表示该集群未使用
这链接说有人使用 fsck 解决了存储卡的类似问题。