【问题标题】:Safely writing to compact flash on embedded Linux在嵌入式 Linux 上安全地写入紧凑型闪存
【发布时间】:2011-01-23 20:03:43
【问题描述】:

我正在开发一个使用紧凑型闪存和 tmpfs 运行的嵌入式 Linux 系统。闪存以只读方式安装,通常应该保持这种状态,但有时我需要向闪存写入一些内容。

写入闪存(通过 PATA 接口)时应该采取哪些预防措施?由于我不记得的原因,我正在使用安装有barrier=1,data=ordered,nodelalloc,noatime,roext4 文件系统这是一个可怕的想法吗?系统需要在零干预的情况下快速启动。我很想做tune2fs -c 0 -i 0。这是一个更糟糕的主意吗?

另外,当我写东西时,我显然需要重新安装闪存读写,执行写入,然后重新安装只读。问题是有几个不同的进程(c++ 二进制和 shell 脚本)可能需要执行此操作。显然,让每个进程在完成后不加选择地以只读方式重新挂载文件系统是一个坏主意。

协调这一点的最佳方式是什么? flock 看起来很有希望;这是最好的方法吗?我需要担心什么?我不希望过时的锁阻止写入或让文件系统无限期地写入。

澄清一下:“偶尔”写入是指系统可以运行多年而无需编写任何东西。当某些东西确实被写入时,它可能是几百个字节。同时,系统需要在没有任何干预的情况下承受不可预测的电源循环。

【问题讨论】:

    标签: linux filesystems locking embedded embedded-linux


    【解决方案1】:

    让 ext4 安全

    ext4 对此并不理想;您最坏的情况总是会在您的分区为 RW 并损坏文件系统时出现电源故障。

    尽管它们是为原始 NAND 设备设计的,但像 jffs2 或 yaffs 这样的日志文件系统可能仍然有用。它们的有用特性是它们的磁盘格式看起来更像一个列表而不是树,因此较新的数据往往被更紧密地打包,因此不太可能破坏文件系统中相对静态的部分。

    我无法评论在这种情况下如何使 ext4 变得“安全”;文件系统结构和 fsck 都不知道闪存设备的常见故障模式(值得注意的是,在任何写入过程中,整个数据块都会在很长一段时间内无效。)当然,这种行为是特定于控制器上的CF卡,所以无论如何都不是很可预测。

    我能想到的最安全和最可预测的方法是在较小的嵌入式设备中使用相同的翻转缓冲区数据布局。也就是说,您有两个可写区域(两个分区)。在任何给定时间,其中至少一个必须是一致的。当你想写的时候,选择两者中较大的一个。如果您启动并检测到缓冲区 A 中的不一致,请复制缓冲区 B 的内容(同时不允许对 B 进行任何写入。)

    管理挂载/重新挂载

    我会编写一个守护进程来代表系统上的所有进程管理卸载/重新安装。这有很多优点:

    • 您将 umount/remount 逻辑分离出来,只需要实现一次
    • 想写的进程不需要root权限
    • 您可以构建某种看门狗,以确保分区不会保留 RW 太久。如果是,您可以终止有问题的进程(可能回滚)并重新挂载-RO。
    • 您可以测量安装 RW 的时间,从而了解每次更新所涉及的风险

    【讨论】:

    • 好点。似乎由于 CF 控制器的抽象,文件系统几乎不可能保证原子操作,不是吗? “翻转缓冲区”方法听起来像是要走的路。通过守护进程管理重新挂载也是一个好主意。在我的情况下,已经有一个守护进程可以完成大部分写入,因此让它管理重新安装是一种自然的扩展。谢谢!
    • 是的 - 我认为你在 CF 控制器抽象问题上是对的。您可以使用一个控制器保证原子性,但不能保证另一个控制器的行为相同。
    • “文件系统结构和 fsck 都不知道闪存设备的常见故障模式(特别是,在任何写入过程中,整个数据块都会在很长一段时间内无效。)。” --- 如果您在谈论闪存的命令模式与读取模式,这无关紧要,因为它已从闪存控制器上方的硬件层中移除。
    • @Casey:我不是。我说的是闪存写入背后的物理过程,而不是它的逻辑接口。你可能只写一个字节的数据,但是一个幼稚的控制器仍然会读取这个块,在内存中修改它,擦除这个块并重写它。
    【解决方案2】:

    我制作了一个使用 4GB CF 卡运行的嵌入式系统。我设置了 3 个分区:

    • /启动;分机2; ~128MB
    • 根;南瓜; 500MB(由于不可写,所以无法意外将其置于写入模式。)
    • /数据;分机2; ~3.5GB 任何我想保存的数据

    我使用 ext2 是因为我相信任何日志 FS 实际上会导致每次写入需要修改更多块。此外,在 CF 卡上运行闪存文件系统也没有任何意义,因为系统无法直接访问闪存块。 CF卡内部包含自己的块映射逻辑。

    【讨论】:

    • 在我的情况下,写入非常罕见,因此我不太关心闪存上的磨损,而更关心文件系统的一致性。
    【解决方案3】:

    由于您使用的是 CF,因此磨损均衡很可能是内置的,因此使用内置磨损均衡的 yaffs2、jffs2 等文件系统不会有任何好处。事实上,大多数磨损均衡文件系统不推荐用于内置磨损均衡的 CF 卡。但您需要一个内置日志的文件系统,以便您可以安全地通过电源开关周期而不会损坏系统。那里有两个选项 - 选择带有日志的文件系统或选择带有像 sqlite 这样的磨损均衡的数据库(假设写入以数据库为中心)。对于文件系统,您可以使用 ext3 或 ext4,尽管我个人推荐使用 ext3,因为 ext4 仍然存在让您头疼的错误。我还建议像其他人一样拥有两个分区,一个使用 squashfs、cramfs 之类的文件系统进行纯只读,另一个使用 ext3 进行读写。

    话虽如此,我不确定您的设备是否内置了 EEPROM,但如果有并且您只需每隔几年写入几百个字节,最简单的配置就是使用单个只读文件EEPROM 作为这几百字节的数据区域。

    【讨论】:

      【解决方案4】:

      我会创建一个单独的分区,并以 rw 方式挂载。

      【讨论】:

      • 我有一个根分区、一个数据分区和一个备用根分区,它在软件升级成功后获取根分区的副本。由于数据分区通常不被写入,我想在大多数情况下将其安装为只读。我是不是太偏执了?
      • 我的意思是你应该有一个专门的数据分区来满足这个读写需求。
      • 我有一个专用分区。它只是很少写入(在某些用例中从不),因此我希望尽可能将其以只读方式安装。我的问题是如何正确地做到这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多