フラッシュベースのストレージ用の軽量循環ログ(ファイルシステムのような)アルゴリズム


8

私は現在、長いライフタイムにわたって、アプリケーション固有のメトリックの迅速で継続的なロギングを含むプロジェクトに取り組んでいます。これを行うには、NXP M0と32MiB SPIフラッシュチップを使用することになりました。ロギングは継続的であり、フィールドで何年も続く必要があり(10+)、トレンドスポッティングについて人間が定期的にチェックします。最終的にバッファがいっぱいになり、古いデータを完全に上書きし始めます。電源を入れた後、フラッシュデバイス全体を歩いて現在のヘッドを見つける簡単なアルゴリズムを考え出しました(デバイスの電源がオフになり、コントロールの外で頻繁に電源が切れます)。私はこの散歩を力ずくで行い、最悪のシナリオとして〜4秒でそれを行うことができます。

これにより、フラッシュデバイスやマイクロコントローラーに対応するログ構造のファイルシステムはありますか?JFFSやその他のよく知られているログ構造化FSは、単純なマイクロコントローラー(もちろん、アプリケーションによって異なります)には少し重くなると思います。具体的には、特にヘッドシーク時間が速い循環ログとして設計されたアルゴリズムや、フラッシュデバイス上の「従来の」ファイルシステム用に設計されたアルゴリズムで、マイクロコントローラー。この意味で伝統的なものは、階層的な名前空間内の可変ランダムアクセスファイルのコレクションを表すデータ構造が存在するJFFSのようなものと同等です。


SDカードのFAT32またはFAT16は遅すぎるのですか?
vicatcu 2012

2
この質問はこのトピックで完全に取り上げられていますが、優れた応答が得られない場合は、StackOverflowが役立つでしょう。ここでいくつかの良い答えが得られることを期待しましょう!
Kellenjb

@vicatcuそれが遅すぎるというわけではありません。私のアプリケーションでは、SDカードとコネクタの方がコストが高く、SDカードの信頼性が低くなる可能性があります。Kellenjbどこに置くべきか分かりませんでした。多くの組み込み設計の質問と同様に、この種の問題は真ん中にあります。ここでうまくいかない場合は、喜んで移動します。
Kris Bahnsen、2012

それは生のフラッシュチップですか?もしそうなら、あなたは死んだブロックをどのように扱いますか?フラッシュFS実装のかなり大きな部分がデッドブロックを処理します。JFFS / JFFS2が非常に重いと感じた場合は、YAFFSを調べてみてください。少なくとも非常にシンプルなファイルシステムのように感じられるため、非常に軽量である必要があります。
レオ

はい、そうです。不良ブロックはこの特定のアプリケーションではひどいものではありません。長期間引き抜かれるデータは大まかな傾向であり、ほとんどの場合、ロギングはまったく使用されないのでです。
Kris Bahnsen 2012年

回答:


2

ロープデータ構造

ロープのデータ構造に魅了されました。ほんの数バイトのRAMが巨大なフラッシュメモリにフックされているマイクロコントローラーに適用しようとしている趣味のプロジェクトがあるので、巨大なテキストファイルの可変長テキストを挿入および削除したり、その他の方法で任意に編集したりできます。テキストファイルが大きすぎてRAMに収まりません。マルチメガバイトのテキストファイルの途中で文字を挿入または削除するたびに、ファイルの後半を消去してフラッシュに再書き込みし、1バイトずつシフトするのは非常に遅くなりますが、データ構造はロープですこれをはるかに速く行うことができます。ロープデータ構造は、このような可変ランダムアクセス可変長ファイルを不変の固定長部分として表すことができるため、フラッシュメモリに適しているようです。すべての編集は、循環ログのような方法で書き込まれます。悲しいかな、すべてのバグが私のコードでまだ解決されていません。:-(

固定長の時系列ログ

開発を支援した製品について、私は同様の循環ログシステムを動作させました。

固定長のレコードを次々に書き込んで、フラッシュを循環配列として埋めていきました。

(完全に空白のフラッシュを使用して、配列の最後の約3ブロック前にレコードの書き込みを開始したため、データのレコードが数レコードだけ格納された後で循環ラップアラウンドをテストできました。私のラップアラウンドコードにバグがあることを知る前に書き込まれる1か月分のデータ。

少なくとも2つの消去済み「消去ブロック」が書き込まれる準備ができていることを確認しました。レコードを書き込んだ後、その後に空の「消去済みブロック」が2つしかなかった場合、無条件に最も古いデータブロックを消去しました。2つの「消去済みブロック」の後の最も古いデータの3番目のブロックです。(フラッシュメモリの終わり近くにある「後」とは、「フラッシュメモリの最初に戻る」ことを意味します。(おそらく、単一の消去済みブロックで十分だったでしょう。少なくとも2つ、時には3つ必要だと思った理由を忘れています) 。

各「消去ブロック」に記録したレコード数を正確に忘れてしまいましたが、2つの消去ブロックにまたがるレコードがないことを確認しました。フラッシュのすべての消去ブロックの最初の2バイトは、「消去済み」値0xFFFF、または各レコードのヘッダーにあるFletcher-16チェックサムの最初の2バイト(決して0xFFFFではない)。

これにより、次に電源を入れたときにすばやくスキャンして循環ログの先頭を見つけることができました。「消去済み」ブロックと「データ」ブロックを区別するために、各消去ブロックの最初の2バイトを調べるだけで済みました。(「ブロックの消去中の電源障害」が原因で最初の2バイトが0xFFFFに消去されるのを少し心配しましたが、消去されていないバイトをブロックの中央に残していたので、マイクロコントローラーがチェックするコードを書きましたこのため、「ブロックの消去」プロセスを再開します。

他のフラッシュ対応のデータ構造またはファイルシステムを見つけたら教えてください。


あなたのアプローチは私のものにいくらか似ているように聞こえます。ただし、もう少しひねりを加えることをお勧めします。各ブロックに数バイトを予約して、それが「開始」され、それが「フル」であることを示します。消去されたブロックを除くすべてのブロックには、「開始」ビットがプログラムされている必要があります。ブロックを消去するときは、データの最後のバイトに「フル」バイトを設定してから、ブロックを消去し、すぐに最も古い消去済みブロックの「開始」ビットを設定します。起動時に、「最後」のブロックが「開始済み」ではなく「完全」であることがわかった場合は、消去をやり直してください。
スーパーキャット2012年

このようなアプローチはやり過ぎに思えるかもしれませんが、フラッシュブロックが部分的に消去されている場合、バイトがFFなどを読み取ることを勝手に決定する可能性があります。ブロックが空白に見えるという事実は、ビットが自然に「出現」しないことを保証するものではありません。消去の進行中に電源が切れた場合は、次の起動時に少し待ってから、ブロックが空白に表示されていても消去を繰り返します
スーパーキャット2012年

情報をありがとうございます。実際にフラッシュストレージのコードにアクセスして、何が起こるかをお知らせする際に、少し詳しく調べます。
クリスバーンセン2012年

@supercat:ありがとう、いいアイデアですね。
davidcary 2012年

@davidcary:完全に空白で表示されなかったブロックがあったことを知りませんが、連続した読み取りで異なる結果をもたらすブロックがありました。ブロックが誤って空白として読み取られた可能性があります。コードがそれをどうにかプログラムしようとしたため、新しいプログラムデータと古い割り込み消去ガベージの奇妙なミッシュモッシュが発生しました。いずれにせよ、ブロックが時々空白に見えるシナリオはほとんど現実的ではありません。
スーパーキャット2012年

0

かなりの年になりますが、他の誰かが迷った場合に備えて、フォローアップしたいと思います。NOR SPIフラッシュをターゲットとするマイクロコントローラー向けのファイルシステムである(2020年1月の時点で)アクティブに維持されている最近のプロジェクトがいくつかあるようです。

私はこれらをどのような容量でもテストしていませんが、元の質問が探していたとおりに動作することに注意してください:「...可変のランダムアクセスファイルのコレクションを表すデータ構造...」

https://github.com/ARMmbed/littlefs-ARMにより作成、BSDライセンス

https://github.com/joembedded/JesFs-実際にはライセンスされていないようですが、SPI NORフラッシュ用に特別に設計されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.