NORフラッシュでのリングバッファの実装

背景

自瀟デザむンの自動販売機もございたす。 Raspberry Pi の内郚ず別のボヌド䞊のいく぀かの配線。コむンアクセプタ、玙幣アクセプタ、銀行端末が接続されおおり、すべおが自䜜のプログラムによっお制埡されおいたす。䜜業履歎党䜓はフラッシュ ドラむブ (MicroSD) 䞊のログに曞き蟌たれ、むンタヌネット (USB モデムを䜿甚) 経由でサヌバヌに送信され、デヌタベヌスに保存されたす。販売情報は 1c にロヌドされ、監芖などのための簡単な Web むンタヌフェむスもありたす。

぀たり、仕蚳垳は䌚蚈 (収益、売䞊など)、監芖 (あらゆる皮類の倱敗やその他の䞍可抗力状況) にずっお䞍可欠です。これが、このマシンに぀いお私たちが知っおいるすべおの情報であるず蚀えるかもしれたせん。

問題

フラッシュ ドラむブは、非垞に信頌性の䜎いデバむスであるこずがわかりたす。圌らはうらやたしいほど定期的に倱敗したす。これにより、マシンのダりンタむムず (䜕らかの理由でログをオンラむンで転送できなかった堎合) デヌタ損倱の䞡方が発生したす。

フラッシュ ドラむブを䜿甚するのはこれが初めおの経隓ではありたせん。これより前には、雑誌が USB フラッシュ ドラむブに保存されおいた 100 台以䞊のデバむスを䜿甚する別のプロゞェクトがありたした。信頌性にも問題があり、倱敗したデバむスの数が倚かったです。 1か月は数十でした。 SLC メモリを搭茉したブランド品など、さたざたなフラッシュ ドラむブを詊したしたが、䞀郚のモデルは他のモデルよりも信頌性が高くなりたすが、フラッシュ ドラむブを亀換しおも問題は根本的に解決されたせんでした。

譊告 長く読んでください 「なぜ」には興味がなく、「どのように」だけに興味がある堎合は、そのたた進んでください。 最終的には 蚘事。

゜リュヌション

最初に思い浮かぶのは、MicroSD を攟棄し、たずえば SSD を取り付けお、そこから起動するこずです。おそらく理論的には可胜ですが、比范的高䟡で、信頌性もそれほど高くありたせん (USB-SATA アダプタヌが远加されたす。䜎予算 SSD の障害統蚈も期埅できるものではありたせん)。

USB HDD も、特に魅力的な゜リュヌションずは思えたせん。

したがっお、MicroSD からの起動はそのたたにしお、読み取り専甚モヌドで䜿甚し、操䜜ログ (および特定のハヌドりェアに固有のその他の情報 - シリアル番号、センサヌのキャリブレヌションなど) を別の堎所に保存するずいうオプションにたどり着きたした。 。

ラズベリヌの読み取り専甚 FS のトピックはすでに培底的に研究されおいるため、この蚘事では実装の詳现に぀いおは觊れたせん。 (ただし、興味があれば、このトピックに関するミニ蚘事を曞くかもしれたせん)。私が泚意したい唯䞀の点は、個人的な経隓からも、すでに導入した人のレビュヌからも、信頌性が向䞊しおいるずいうこずです。はい、故障を完党になくすこずは䞍可胜ですが、故障の頻床を倧幅に枛らすこずはかなり可胜です。たた、カヌドは統合され぀぀あるため、サヌビス担圓者による亀換がはるかに簡単になりたす。

ハヌドりェア

メモリの皮類である NOR フラッシュの遞択に特に疑問はありたせんでした。
匕数

  • 簡単な接続 (ほずんどの堎合、SPI バスを䜿甚したす。すでに䜿甚経隓があるため、ハヌドりェアの問題は発生したせん)。
  • ずんでもない倀段。
  • 暙準動䜜プロトコル (実装はすでに Linux カヌネルに組み蟌たれおいたす。必芁に応じお、同様に存圚するサヌドパヌティ補のプロトコルを䜿甚するこずも、独自のプロトコルを䜜成するこずもできたす。幞いなこずに、すべおが簡単です)。
  • 信頌性ずリ゜ヌス:
    䞀般的なデヌタシヌトより: デヌタは 20 幎間保存され、ブロックごずに 100000 回の消去サむクルが行われたす。
    サヌドパヌティの゜ヌスから: BER が非垞に䜎く、゚ラヌ蚂正コヌドが䞍芁であるず想定されたす。 (䞀郚の䜜品では ECC を NOR ずみなしたすが、通垞は䟝然ずしお MLC NOR を意味したす。これも起こりたす).

ボリュヌムずリ゜ヌスの芁件を芋積もっおみたしょう。

デヌタの数日間の保存を保蚌しおほしい。これは、通信䞊の問題が発生した堎合に販売履歎が倱われないようにするために必芁です。この期間䞭、5日間に焊点を圓おたす。 土日祝日も考慮に入れたす 問題は解決できたす。

珟圚、100 日あたり玄 3 kb のログ (4  10 ゚ントリ) を収集しおいたすが、この数字は埐々に増加しおおり、詳现が増加し、新しいむベントが远加されおいたす。さらに、バヌストが発生するこずもありたす (たずえば、䞀郚のセンサヌが誀怜知でスパム送信を開始したす)。 100 レコヌドに぀いお、それぞれ XNUMX バむト、぀たり XNUMX 日あたりメガバむトを蚈算したす。

合蚈 5MB のクリヌンな (適切に圧瞮された) デヌタが出力されたす。もっず圌らに おおたかな芋積もり 1MBのサヌビスデヌタ。

぀たり、圧瞮を䜿甚しない堎合は 8MB のチップが必芁ずなり、圧瞮を䜿甚する堎合は 4MB のチップが必芁になりたす。このタむプのメモリでは非垞に珟実的な数倀です。

リ゜ヌスに関しおは、メモリ党䜓が 5 日に 10 回以䞊曞き換えられないず蚈画した堎合、XNUMX 幎間䜿甚しおも曞き換えサむクルは XNUMX 回未満になりたす。
メヌカヌは10䞇個を玄束しおいるこずを思い出させおください。

NOR ず NAND に぀いお少し説明

Today, of course, NAND memory is much more popular, but I would not use it for this project: NAND, unlike NOR, necessarily requires the use of error correction codes, a table of bad blocks, etc., and also the legs of通垞、NAND チップはさらに倚くなりたす。

NOR の欠点は次のずおりです。

  • ボリュヌムが小さいしたがっお、メガバむトあたりの䟡栌が高い。
  • 通信速床が遅い (シリアル むンタヌフェむス (通垞は SPI たたは I2C) が䜿甚されるこずが䞻な原因)。
  • 遅い消去 (ブロック サむズに応じお、数秒から数秒かかりたす)。

私たちにずっお重芁なものは䜕もないようなので、続行したす。

詳现に興味がある堎合は、マむクロ回路が遞択されおいたす at25df321a (ただし、これは重芁ではありたせん。ピン配列ずコマンド システムで互換性のある類䌌品が垂堎に倚数存圚したす。異なるメヌカヌや異なるサむズの超小型回路を取り付けたい堎合でも、すべおが倉曎せずに機胜したす。コヌド.

私は Linux カヌネルに組み蟌たれおいるドラむバヌを䜿甚しおいたすが、Raspberry では、デバむス ツリヌ オヌバヌレむ サポヌトのおかげで、すべおが非垞に簡単です - コンパむルされたオヌバヌレむを /boot/overlays に眮き、/boot/config.txt を少し倉曎するだけです。

dts ファむルの䟋

正盎に蚀うず、゚ラヌなく曞かれおいるかどうかはわかりたせんが、正垞に動䜜したす。

/*
 * Device tree overlay for at25 at spi0.1
 */

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; 

    /* disable spi-dev for spi0.1 */
    fragment@0 {
        target = <&spi0>;
        __overlay__ {
            status = "okay";
            spidev@1{
                status = "disabled";
            };
        };
    };

    /* the spi config of the at25 */
    fragment@1 {
        target = <&spi0>;
        __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;
            flash: m25p80@1 {
                    compatible = "atmel,at25df321a";
                    reg = <1>;
                    spi-max-frequency = <50000000>;

                    /* default to false:
                    m25p,fast-read ;
                    */
            };
        };
    };

    __overrides__ {
        spimaxfrequency = <&flash>,"spi-max-frequency:0";
        fastread = <&flash>,"m25p,fast-read?";
    };
};

そしおconfig.txtの別の行

dtoverlay=at25:spimaxfrequency=50000000

チップずRaspberry Piの接続に぀いおは説明を省略したす。䞀方では、私ぱレクトロニクスの専門家ではありたせんが、他方では、ここにあるこずは私にずっおさえありふれたものです。超小型回路には 8 本の脚しかなく、そのうちのグランド、電源、SPI (CS、SI、SO、SCK) が必芁です。 );レベルは Raspberry Pi ず同じで、远加の配線は必芁ありたせん。指定された 6 ぀のピンを接続するだけです。

問題の定匏化

い぀ものように、問題ステヌトメントは䜕床か反埩され、次の反埩の時期が来たように思えたす。そこで、ここで立ち止たっお、すでに曞かれたこずをたずめお、圱に残っおいる詳现を明らかにしたしょう。

そこで、ログを SPI NOR Flash に保存するこずにしたした。

知らない人のために、NOR Flash ずは䜕ですか?

これは、次の 3 ぀の操䜜を実行できる䞍揮発性メモリです。

  1. 読む
    最も䞀般的な読み取り: アドレスを送信し、必芁なだけバむトを読み取りたす。
  2. 蚘録
    NOR フラッシュぞの曞き蟌みは通垞の曞き蟌みのように芋えたすが、特城が 1 ぀ありたす。0 から 0 ぞの倉曎のみが可胜で、その逆はできないずいうこずです。たずえば、メモリ セルに 55x0 があった堎合、0x0f を曞き蟌んだ埌、05xXNUMX がすでにそこに栌玍されおいたす。 (すぐ䞋の衚を参照);
  3. 消去
    もちろん、逆の操䜜、぀たり 0 を 1 に倉曎するこずができる必芁がありたす。これがたさに消去操䜜の目的です。最初の 4 ぀ずは異なり、バむトではなくブロックで動䜜したす (遞択したチップの最小消去ブロックは 0kb です)。消去はブロック党䜓を砎壊し、1 を XNUMX に倉曎する唯䞀の方法です。したがっお、フラッシュ メモリを䜿甚する堎合、倚くの堎合、デヌタ構造を消去ブロックの境界に揃える必芁がありたす。
    NOR フラッシュでの蚘録:

バむナリデヌタ

だった
01010101

録音枈み
00001111

なった
00000101

ログ自䜓は、可倉長のレコヌドのシヌケンスを衚したす。レコヌドの長さは通垞玄 30 バむトです (ただし、レコヌドの長さが数キロバむトになる堎合もありたす)。 この堎合、それらを単にバむトのセットずしお扱いたすが、興味がある堎合は、レコヌド内で CBOR が䜿甚されたす。

ログに加えお、特定のデバむス ID、センサヌの調敎、「デバむスが䞀時的に無効になっおいる」フラグなど、曎新されたものずそうでないものを含むいく぀かの「蚭定」情報を保存する必芁がありたす。
この情報はキヌず倀のレコヌドのセットであり、CBOR にも保存されおいたすが、この情報はそれほど倚くはなく (せいぜい数キロバむト)、曎新される頻床も䜎いです。
以䞋では、それをコンテキストず呌びたす。

この蚘事の始たりを思い出しおください。信頌性の高いデヌタ ストレヌゞを確保し、可胜であれば、ハヌドりェア障害やデヌタ砎損が発生した堎合でも継続的な運甚を確保するこずが非垞に重芁です。

どのような問題の原因が考えられたすか?

  • 曞き蟌み/消去操䜜䞭は電源をオフにしおください。これは「バヌルに察抗する術はない」ずいうカテゎリヌのものです。
    からの情報 議論 stackexchange: フラッシュの操䜜䞭に電源がオフになるず、消去 (1 に蚭定) ず曞き蟌み (0 に蚭定) の䞡方が未定矩の動䜜を匕き起こしたす: デヌタは曞き蟌むこずができ、郚分的に曞き蟌むこずができたす (たずえば、10 バむト/80 ビットを転送したずしたす) 、ただしただ 45 ビットしか曞き蟌むこずができたせん、䞀郚のビットが「䞭間」状態になる可胜性もありたす読み取りでは 0 ず 1 の䞡方が生成される可胜性がありたす。
  • フラッシュメモリ自䜓の゚ラヌ。
    BER は非垞に䜎いですが、れロに等しくするこずはできたせん。
  • バス゚ラヌ
    SPI 経由で送信されるデヌタはいかなる方法でも保護されおおらず、単䞀ビット ゚ラヌず同期゚ラヌの䞡方が発生する可胜性がありたす - ビットの損倱たたは挿入 (倧芏暡なデヌタ歪みに぀ながりたす)。
  • その他の゚ラヌ/䞍具合
    コヌドの゚ラヌ、ラズベリヌの䞍具合、゚むリアンの干枉...

私は芁件を策定したしたが、私の考えでは、信頌性を確保するにはその芁件を満たすこずが必芁です。

  • レコヌドは盎ちにフラッシュ メモリに保存される必芁があり、遅延曞き蟌みは考慮されたせん。 - ゚ラヌが発生した堎合は、できるだけ早く怜出しお凊理する必芁がありたす。 - 可胜であれば、システムぱラヌから回埩する必芁がありたす。
    (人生における「こうあるべきではない」䟋。誰もが遭遇したこずがあるず思いたす。緊急再起動埌、ファむル システムが「壊れ」、オペレヌティング システムが起動しなくなる)

アむデア、アプロヌチ、考察

この問題に぀いお考え始めたずき、次のような倚くのアむデアが頭の䞭に浮かびたした。

  • デヌタ圧瞮を䜿甚したす。
  • たずえば、レコヌド自䜓ずは別にレコヌド ヘッダヌを保存するなど、賢いデヌタ構造を䜿甚しお、レコヌドに゚ラヌがあった堎合でも問題なく残りを読み取るこずができたす。
  • ビットフィヌルドを䜿甚しお、電源がオフになったずきの蚘録の完了を制埡したす。
  • すべおのチェックサムを保存したす。
  • 䜕らかの皮類のノむズ耐性のあるコヌディングを䜿甚したす。

これらのアむデアのいく぀かは䜿甚されたしたが、他のアむデアは攟棄されるこずが決定されたした。順番に行きたしょう。

デヌタ圧瞮

私たちが日蚘に蚘録する出来事自䜓は非垞に類䌌しおおり、再珟可胜です「5 ルヌブル硬貚を投げた」、「お぀りを枡すためにボタンを抌した」など。したがっお、圧瞮は非垞に効果的であるはずです。

圧瞮オヌバヌヘッドはわずかであり (圓瀟のプロセッサは非垞に匷力で、最初の Pi でさえ呚波数 700 MHz のコアが XNUMX ぀ありたしたが、珟圚のモデルには呚波数 XNUMX ギガヘルツを超えるコアがいく぀かありたす)、ストレヌゞずの亀換レヌトは䜎くなりたす (数メガバむト/秒)、レコヌドのサむズは小さいです。䞀般に、圧瞮がパフォヌマンスに圱響を䞎える堎合、それはプラスの圱響しかありたせん。 たったく批刀的ではなく、単に述べおいるだけです。さらに、本物の組み蟌みではなく、通垞の Linux を䜿甚しおいるため、実装には倚くの劎力は必芁ありたせん (ラむブラリをリンクし、そこからいく぀かの関数を䜿甚するだけで十分です)。

動䜜䞭のデバむスからログの䞀郚 (1.7 MB、70 ゚ントリ) が取埗され、最初にコンピュヌタヌで利甚可胜な gzip、lz4、lzop、bzip2、xz、zstd を䜿甚しお圧瞮性がチェックされたした。

  • gzip、xz、zstd も同様の結果を瀺したした (40Kb)。
    ファッショナブルな xz が gzip たたは zstd のレベルでここに珟れたこずには驚きたした。
  • デフォルト蚭定の lzip では、若干悪い結果が埗られたした。
  • lz4 ず lzop はあたり良い結果を瀺したせんでした (150Kb)。
  • bzip2 は驚くほど良い結果を瀺したした (18Kb)。

したがっお、デヌタは非垞によく圧瞮されおいたす。
したがっお、(臎呜的な欠陥が芋぀からなければ) 圧瞮が行われるこずになりたす。より倚くのデヌタを同じフラッシュドラむブに保存できるためです。

デメリットに぀いお考えおみたしょう。

最初の問題: すべおのレコヌドが盎ちにフラッシュされる必芁があるこずにすでに同意しおいたす。通垞、アヌカむバヌは、週末に曞き蟌みを行う時期が来たず刀断するたで、入力ストリヌムからデヌタを収集したす。デヌタの圧瞮ブロックを盎ちに受信し、䞍揮発性メモリに保存する必芁がありたす。

私は次の 3 ぀の方法を考えおいたす。

  1. 䞊で説明したアルゎリズムの代わりに蟞曞圧瞮を䜿甚しお各レコヌドを圧瞮したす。
    これは完党に機胜するオプションですが、私は奜きではありたせん。 Для ПбеспечеМОя бПлее-ЌеМее прОлОчМПгП урПвМя сжатОя слПварь ЎПлжеМ быть «затПчеМ» пПЎ кПМкретМые ЎаММые, любПе ОзЌеМеМОе прОвеЎёт к тПЌу, чтП урПвеМь сжатОя катастрПфОческО паЎает. Да, прПблеЌа решается сПзЎаМОеЌ МПвПй версОО слПваря, МП этП же гПлПвМая бПль — МаЌ МужМП буЎет храМОть все версОО слПваря;各゚ントリでは、どのバヌゞョンの蟞曞で圧瞮されたかを瀺す必芁がありたす...
  2. 「叀兞的な」アルゎリズムを䜿甚しお各レコヌドを圧瞮したすが、他のレコヌドは独立しお圧瞮されたす。
    怜蚎䞭の圧瞮アルゎリズムは、このサむズ (数十バむト) のレコヌドを凊理するように蚭蚈されおいないため、圧瞮率は明らかに 1 未満になりたす (぀たり、圧瞮ではなくデヌタ量が増加したす)。
  3. 各蚘録埌にフラッシュを実行したす。
    倚くの圧瞮ラむブラリは FLUSH をサポヌトしおいたす。これはコマンド (たたは圧瞮手順のパラメヌタヌ) であり、アヌカむバヌはこれを受信するず圧瞮ストリヌムを圢成し、埩元に䜿甚できるようにしたす。 すべお すでに受信した非圧瞮デヌタ。そんなアナログ sync ファむルシステム内、たたは commit SQLで。
    重芁なこずは、埌続の圧瞮操䜜で蓄積された蟞曞を䜿甚できるようになり、圧瞮率が以前のバヌゞョンほど䜎䞋しないこずです。

私が 3 番目のオプションを遞択したのは明らかだず思いたす。詳しく芋おみたしょう。

芋぀かった 玠晎らしい蚘事 zlibのFLUSHに぀いお。

蚘事に基づいお膝テストを実行し、ペヌゞ サむズ 70Kb で実際のデバむスから 60 のログ ゚ントリを取埗したした。 (ペヌゞサむズに぀いおは埌ほど説明したす) 受け取った

初期デヌタ
圧瞮 gzip -9 (フラッシュなし)
Z_PARTIAL_FLUSH を䜿甚した zlib
Z_SYNC_FLUSH を䜿甚した zlib

ボリュヌム、KB
1692
40
352
604

䞀芋するず、FLUSH によるコストが高すぎるように芋えたすが、実際には、たったく圧瞮しないか、FLUSH で (そしお非垞に効果的に) 圧瞮するか、ほずんど遞択肢がありたせん。 70 䞇件のレコヌドがあるこずを忘れおはなりたせん。Z_PARTIAL_FLUSH によっお導入される冗長性は、レコヌドあたりわずか 4  5 バむトです。圧瞮率はほが 5:1 であるこずが刀明し、これは非垞に優れた結果です。

驚くかもしれたせんが、Z_SYNC_FLUSH は実際には FLUSH を実行するより効率的な方法です。

Z_SYNC_FLUSH を䜿甚する堎合、各゚ントリの最埌の 4 バむトは垞に 0x00、0x00、0xff、0xff になりたす。そしお、それらがわかっおいれば、保存する必芁がないため、最終的なサむズはわずか 324Kb になりたす。

私がリンクした蚘事には次のような説明がありたす。

䞭身が空の新しいタむプ 0 ブロックが远加されたす。

䞭身が空のタむプ 0 ブロックは次のもので構成されたす。

  • 3 ビットのブロックヘッダヌ。
  • 0  7 ビットはれロに等しく、バむト アラむンメントを実珟したす。
  • 00 バむトのシヌケンス 00 XNUMX FF FF。

簡単にわかるように、これら 4 バむトの前の最埌のブロックには 3  10 個のれロ ビットがありたす。ただし、実際には少なくずも 10 個のれロ ビットがあるこずがわかっおいたす。

このような短いデヌタ ブロックは、通垞 (垞に?) タむプ 1 のブロック (固定ブロック) を䜿甚しお゚ンコヌドされるこずがわかりたした。このブロックは必ず 7 ぀のれロ ビットで終わり、合蚈 10  17 の保蚌されたれロ ビットになりたす (残りは玄50%の確率でれロになりたす。

したがっお、テスト デヌタでは、100% の堎合、0x00、0x00、0xff、0xff の前にれロ バむトが XNUMX ぀あり、XNUMX 分の XNUMX 以䞊のケヌスで XNUMX ぀のれロ バむトがありたす。 (おそらく実際にはバむナリ CBOR を䜿甚しおおり、テキスト JSON を䜿甚する堎合、タむプ 2 のブロック (ダむナミック ブロック) がより䞀般的であり、0x00、0x00、0xff、0xff の前に远加のれロ バむトがないブロックが発生したす).

利甚可胜なテスト デヌタを䜿甚するず、合蚈で 250Kb 未満の圧瞮デヌタに収めるこずができたす。

ビットを調敎するこずで、もう少し節玄できたす。今のずころ、ブロックの終わりにあるいく぀かのれロビットの存圚を無芖したす。ブロックの先頭にあるいく぀かのビットも倉曎されたせん...
しかし、このたたでは独自のアヌカむバを開発するこずになるかもしれないので、やめようず匷い意志を持ちたした。

合蚈するず、曞き蟌みごずに 3  4 バむトを受信したテスト デヌタから、圧瞮率は 6:1 を超えるこずが刀明したした。正盎に蚀うず、このような結果になるずは予想しおいたせんでした。私の意芋では、2:1 よりも優れたものはすでに圧瞮の䜿甚を正圓化する結果になっおいたす。

すべお問題ありたせんが、zlib (deflate) は䟝然ずしお叀颚で、圓然のこずであり、やや時代遅れの圧瞮アルゎリズムです。非圧瞮デヌタ ストリヌムの最埌の 32Kb が蟞曞ずしお䜿甚されるずいう単なる事実は、今日では奇劙に芋えたす (぀たり、あるデヌタ ブロックが 40Kb 前の入力ストリヌムにあったものず非垞によく䌌おいる堎合、そのデヌタ ブロックは再びアヌカむブされ始めたす)以前の出来事に぀いおは蚀及したせん。最新のファッショナブルなアヌカむバでは、蟞曞のサむズはキロバむトではなくメガバむトで枬定されるこずがよくありたす。

そこで私たちはアヌカむバに関するミニ研究を続けたす。

次に、bzip2 をテストしたした (FLUSH を䜿甚しないず、ほが 100:1 ずいう玠晎らしい圧瞮率が瀺されたこずを思い出しおください)。残念ながら、FLUSH ではパフォヌマンスが非垞に悪く、圧瞮デヌタのサむズが非圧瞮デヌタよりも倧きいこずが刀明したした。

倱敗の理由に぀いおの私の掚枬

Libbz2 が提䟛するフラッシュ オプションは XNUMX ぀だけで、蟞曞をクリアするようです (zlib の Z_FULL_FLUSH に䌌おいたす)。これ以降は効果的な圧瞮に぀いおは蚀及されおいたせん。

そしお最埌にテストされたのは zstd でした。パラメヌタに応じお、gzip レベルで圧瞮したすが、gzip よりもはるかに高速か、より優れた圧瞮が行われたす。

残念ながら、FLUSH ではパフォヌマンスがあたり良くありたせんでした。圧瞮デヌタのサむズは玄 700Kb でした。

Я 質問した プロゞェクトの github ペヌゞで、圧瞮デヌタのブロックごずに最倧 10 バむトのサヌビス デヌタを考慮する必芁があるずいう回答を受け取りたしたが、これは埗られた結果に近いものであり、deflate に远い぀く方法はありたせん。

私はアヌカむバヌを䜿った実隓をこの時点で䞭止するこずにしたした (xz、lzip、lzo、lz4 は FLUSH なしのテスト段階でも衚瀺されず、さらに特殊な圧瞮アルゎリズムは考慮しおいたせんでした)。

アヌカむブの問題に戻りたしょう。

2 番目の問題 (倀ではなく順序の問題) は、圧瞮デヌタが単䞀のストリヌムであり、その䞭で垞に前のセクションぞの参照が存圚するこずです。したがっお、圧瞮デヌタのセクションが砎損するず、関連する非圧瞮デヌタのブロックだけでなく、それ以降のブロックもすべお倱われたす。

この問題を解決するには、次のようなアプロヌチがありたす。

  1. 問題の発生を防止したす。圧瞮デヌタに冗長性を远加したす。これにより、゚ラヌを特定しお修正できるようになりたす。これに぀いおは埌で説明したす。
  2. 問題が発生した堎合の圱響を最小限に抑える
    各デヌタ ブロックを個別に圧瞮できるこずはすでに述べたしたが、問題は自然に解消されたす (4 ぀のブロックのデヌタが損傷するず、そのブロックのデヌタのみが倱われたす)。 ОЎМакП, этП крайМОй случай, прО кПтПрПЌ сжатОе ЎаММых буЎет МеэффектОвМП.逆の極端: チップの XNUMXMB をすべお XNUMX ぀のアヌカむブずしお䜿甚するず、優れた圧瞮が可胜になりたすが、デヌタ砎損の堎合は壊滅的な結果になりたす。
    はい、信頌性の点で劥協が必芁です。しかし、私たちは BER が非垞に䜎く、宣蚀されたデヌタ保存期間が 20 幎である䞍揮発性メモリ甚のデヌタ保存圢匏を開発しおいるこずを忘れおはなりたせん。

実隓䞭に、サむズが 10 KB 未満の圧瞮デヌタのブロックで、倚かれ少なかれ顕著な圧瞮レベルの損倱が始たるこずがわかりたした。
䜿甚されるメモリがペヌゞングされるず前述したしたが、「1 ペヌゞず圧瞮デヌタの 1 ブロック」の察応関係を䜿甚すべきではない理由はわかりたせん。

぀たり、適切な最小ペヌゞ サむズは 16Kb (サヌビス情報甚の予玄を含む) です。ただし、ペヌゞ サむズがこのように小さいず、最倧レコヌド サむズに重倧な制限が課せられたす。

圧瞮圢匏で数キロバむトを超えるレコヌドはただ期埅しおいたせんが、32 キロバむトのペヌゞ (チップごずに合蚈 128 ペヌゞ) を䜿甚するこずにしたした。

抂芁

  • デヌタは zlib (deflate) を䜿甚しお圧瞮しお保存したす。
  • ゚ントリごずに Z_SYNC_FLUSH を蚭定したす。
  • 圧瞮されたレコヌドごずに、末尟のバむトをトリミングしたす。 (䟋: 0x00、0x00、0xff、0xff);ヘッダヌでは、切り取るバむト数を瀺したす。
  • デヌタは 32Kb ペヌゞに保存されたす。ペヌゞ内には圧瞮デヌタの単䞀ストリヌムがありたす。各ペヌゞで再び圧瞮を開始したす。

そしお、圧瞮を終える前に、レコヌドあたりの圧瞮デヌタは数バむトしかないずいう事実に泚意しおいただきたいず思いたす。そのため、サヌビス情報を膚匵させないこずが非垞に重芁であり、ここではすべおのバむトが重芁になりたす。

デヌタヘッダヌの保存

可倉長のレコヌドがあるため、レコヌドの配眮/境界を䜕らかの方法で決定する必芁がありたす。

私は 3 ぀のアプロヌチを知っおいたす。

  1. すべおのレコヌドは連続ストリヌムに栌玍されたす。最初に長さを含むレコヌド ヘッダヌがあり、次にレコヌド自䜓が栌玍されたす。
    この実斜圢態では、ヘッダずデヌタの䞡方を可倉長にするこずができる。
    基本的に、垞に䜿甚される単䞀リンクのリストを取埗したす。
  2. ヘッダヌずレコヌド自䜓は別のストリヌムに保存されたす。
    䞀定の長さのヘッダヌを䜿甚するこずで、1 ぀のヘッダヌの損傷が他のヘッダヌに圱響を䞎えないようにしたす。
    同様のアプロヌチは、たずえば倚くのファむル システムで䜿甚されおいたす。
  3. レコヌドは連続ストリヌムに栌玍され、レコヌドの境界は特定のマヌカヌ (デヌタ ブロック内で犁止されおいる文字たたは文字のシヌケンス) によっお決定されたす。レコヌド内にマヌカヌがある堎合は、それを䜕らかのシヌケンスに眮き換えたす (゚スケヌプしたす)。
    同様のアプロヌチは、たずえば PPP プロトコルでも䜿甚されたす。

説明したす。

オプション1
NORフラッシュでのリングバッファの実装
ここではすべおが非垞に簡単です。レコヌドの長さがわかれば、次のヘッダヌのアドレスを蚈算できたす。したがっお、0xff (空き領域) で満たされた領域たたはペヌゞの終わりに到達するたで、芋出しを移動したす。

オプション2
NORフラッシュでのリングバッファの実装
レコヌド長は可倉であるため、ペヌゞごずに必芁なレコヌド (したがっおヘッダヌ) の数を事前に蚀うこずはできたせん。ヘッダヌずデヌタ自䜓を別のペヌゞに分散するこずもできたすが、私は別のアプロヌチを奜みたす。ヘッダヌずデヌタの䞡方を 1 ぀のペヌゞに配眮したすが、ヘッダヌ (䞀定サむズ) はペヌゞの先頭から来お、 (可倉長の) デヌタは最埌から来たす。これらが「䞀臎」するずすぐに (新しい゚ントリを入力するための十分な空きスペヌスがなくなり)、このペヌゞは完成したず芋なされたす。

オプション3
NORフラッシュでのリングバッファの実装
ヘッダヌ内のデヌタの䜍眮に関する長さたたはその他の情報を保存する必芁はなく、レコヌドの境界を瀺すマヌカヌで十分です。ただし、曞き蟌み/読み取り時にはデヌタを凊理する必芁がありたす。
私は 0xff をマヌカヌ (消去埌にペヌゞを埋める) ずしお䜿甚するので、空き領域はデヌタずしお扱われたせん。

比范衚

オプション1
オプション2
オプション3

蚱容誀差
-
+
+

コンパクトさ
+
-
+

実装の耇雑さ
*
**
**

オプション 1 には臎呜的な欠陥がありたす。ヘッダヌのいずれかが砎損するず、埌続のチェヌン党䜓が砎壊されたす。残りのオプションを䜿甚するず、倧芏暡な損傷が発生した堎合でも䞀郚のデヌタを回埩できたす。
ただし、ここでは、デヌタを圧瞮圢匏で保存するこずにしたため、レコヌドが「壊れた」埌はペヌゞ䞊のすべおのデヌタが倱われるため、テヌブルにマむナスがあっおも、デヌタは倱われたせん。それを考慮に入れおください。

コンパクトさ

  • 最初のオプションでは、ヘッダヌに長さのみを栌玍する必芁がありたす。可倉長の敎数を䜿甚する堎合、ほずんどの堎合、1 バむトで枈みたす。
  • 4 番目のオプションでは、開始アドレスず長さを保存する必芁がありたす。レコヌドは䞀定のサむズである必芁があり、レコヌドごずに XNUMX バむトず芋積もられたす (オフセットに XNUMX バむト、長さに XNUMX バむト)。
  • третьеЌу варОаМту ЎПстатПчМП всегП ПЎМПгП сОЌвПла Ўля ПбПзМачеМОя Мачала запОсО, плюс саЌа запОсь Оз-за экраМОрПваМОя вырастет Ма 1-2%.䞀般に、最初のオプションずほが同等です。

圓初、私は 2 番目のオプションを䞻なオプションずしお怜蚎したした (実装たで曞きたした)。最終的に圧瞮を䜿甚するこずに決めたずきにのみ、それを攟棄したした。

おそらくい぀か私も同じようなオプションを䜿うこずになるでしょう。たずえば、地球ず火星の間を航行する船のデヌタ ストレヌゞを扱う必芁がある堎合、信頌性、宇宙攟射線などに関しおたったく異なる芁件が存圚したす。

3 番目のオプションに぀いおは、シヌルドをいじったり、プロセス内で長さを倉曎したりするのが奜きではないため、実装の難しさを理由に星 2 ぀ずしたした。はい、おそらく私は偏芋を持っおいるかもしれたせんが、コヌドを曞かなければなりたせん。なぜ気に入らないこずを自分に匷制する必芁がありたすか。

抂芁 効率性ず実装の容易さのため、「長さのあるヘッダヌ - 可倉長のデヌタ」ずいうチェヌンの圢匏のストレヌゞ オプションを遞択したす。

ビットフィヌルドを䜿甚しお曞き蟌み操䜜の成功を監芖する

どこでこのアむデアを思い぀いたのか今では芚えおいたせんが、次のような感じです。
各゚ントリに察しお、フラグを栌玍するためにいく぀かのビットを割り圓おたす。
前に述べたように、消去埌はすべおのビットが 1 で埋められ、1 を 0 に倉曎するこずはできたすが、その逆はできたせん。 したがっお、「フラグが蚭定されおいない」堎合は 1 を䜿甚し、「フラグが蚭定されおいる」堎合は 0 を䜿甚したす。

可倉長レコヌドをフラッシュに入れるず次のようになりたす。

  1. 「長さの蚘録が開始されたした」フラグを蚭定したす。
  2. 長さを蚘録したす。
  3. 「デヌタ蚘録が開始されたした」フラグを蚭定したす。
  4. 私たちはデヌタを蚘録したす。
  5. 「録画終了」フラグを立おたす。

さらに、「゚ラヌ発生」フラグがあり、合蚈 4 ビットのフラグになりたす。

この堎合、「1111」 - 録音が開始されおいない、「1000」 - 録音が成功したずいう XNUMX ぀の安定状態がありたす。蚘録プロセスが予期せず䞭断された堎合は、䞭間状態を受け取り、それを怜出しお凊理できたす。

このアプロヌチは興味深いものですが、突然の停電や同様の障害から保護するだけであり、これはもちろん重芁ですが、これが障害の可胜性がある唯䞀の (たたは䞻な) 原因ずいうわけではありたせん。

抂芁 良い解決策を探しお先に進みたしょう。

チェックサム

チェックサムを䜿甚するず、曞き蟌たれるべき内容を正確に読み取っおいるこずを (劥圓な確率で) 確認するこずもできたす。たた、䞊で説明したビット フィヌルドずは異なり、垞に機胜したす。

䞊で説明した朜圚的な問題の原因のリストを考慮するず、チェックサムぱラヌの原因に関係なく゚ラヌを認識できたす。 (おそらく、悪意のある゚むリアンは陀きたす - 圌らもチェックサムを停造するこずができたす).

したがっお、デヌタが損なわれおいないこずを確認するこずが目的である堎合、チェックサムは玠晎らしいアむデアです。

チェックサムを蚈算するアルゎリズムの遞択 (CRC) には䜕の疑問も生じたせんでした。 С ПЎМПй стПрПМы, ЌатеЌатОческОе свПйства пПзвПляют в 100% лПвОть ПшОбкО МекПтПрых тОпПв, с ЎругПй — Ма случайМых ЎаММых ПбычМП этПт алгПрОтЌ пПказывает верПятМПсть кПллОзОй Ме сОльМП бПльше теПретОческПгП преЎела NORフラッシュでのリングバッファの実装。これは最速のアルゎリズムではないかもしれたせんし、衝突の数の点で垞に最小であるわけでもありたせんが、非垞に重芁な性質を持っおいたす。私が遭遇したテストでは、明らかに倱敗するパタヌンはありたせんでした。この堎合、安定性が䞻な品質です。

䜓積調査の䟋: パヌト1, パヌト2 (narod.ru ぞのリンク、申し蚳ありたせん).

ただし、チェックサムを遞択するタスクは完了しおいたせん。CRC はチェックサムのファミリヌ党䜓です。長さを決定しおから、倚項匏を遞択する必芁がありたす。

チェックサムの長さの遞択は、䞀芋したように芋えるほど簡単な問題ではありたせん。

説明したしょう:
各バむトの゚ラヌの確率を調べおみたしょう NORフラッシュでのリングバッファの実装 理想的なチェックサムを求めお、100 䞇レコヌドあたりの平均゚ラヌ数を蚈算しおみたしょう。

デヌタ、バむト
チェックサム、バむト
怜出されない゚ラヌ
誀った゚ラヌ怜出
合蚈誀怜知数

1
0
1000
0
1000

1
1
4
999
1003

1
2
≈0
1997
1997

1
4
≈0
3990
3990

10
0
9955
0
9955

10
1
39
990
1029

10
2
≈0
1979
1979

10
4
≈0
3954
3954

1000
0
632305
0
632305

1000
1
2470
368
2838

1000
2
10
735
745

1000
4
≈0
1469
1469

すべおが単玔であるように思えたす。保護されるデヌタの長さに応じお、誀った正の倀が最小限になるチェックサムの長さを遞択したす。そしお、その秘蚣はバッグの䞭にありたす。

ОЎМакП, с кПрПткОЌО кПМтрПльМыЌО суЌЌаЌО вПзМОкает прПблеЌа: ПМО, хПть О хПрПшП ПбМаружОвают еЎОМОчМые бОтПвые ПшОбкО, ЌПгут с ЎПстатПчМП бПльшПй верПятМПстью прОМять за верМые сПвершеММП случайМые ЎаММые.ハブレに関する蚘事がすでにありたした。 実生掻における問題.

したがっお、ランダムなチェックサムの䞀臎をほが䞍可胜にするには、32 ビット以䞊の長さのチェックサムを䜿甚する必芁がありたす。 (64 ビットを超える長さの堎合は、通垞、暗号化ハッシュ関数が䜿甚されたす).

スペヌスを必ず節玄する必芁があるず以前に曞きたしたが、それでも 32 ビットのチェックサムを䜿甚したす (16 ビットでは十分ではなく、衝突の確率は 0.01% を超えたす。たた、24 ビットも䜿甚したす)。ここにもあそこにもいないず蚀う。

ここで反論が生じるかもしれたせん。䞀床に 4 バむトを䞎えるために、圧瞮を遞択したずきにすべおのバむトを保存したのでしょうか?圧瞮したりチェックサムを付加したりしない方が良いのではないでしょうかもちろんそうではありたせん、圧瞮はありたせん 意味ではありたせん、敎合性チェックは必芁ないずいうこずです。

倚項匏を遞択するずきは、車茪の再発明ではなく、珟圚人気のある CRC-32C を採甚したす。
このコヌドは、最倧 6 バむトのパケットの 22 ビット ゚ラヌ (おそらく圓瀟にずっお最も䞀般的なケヌス)、最倧 4 バむトのパケットの 655 ビット ゚ラヌ (これも圓瀟にずっお䞀般的なケヌス)、パケットの 2 ビットたたは任意の奇数のビット ゚ラヌを怜出したす。 of any reasonable length.

詳现に興味のある方がいらっしゃいたしたら

りィキペディアの蚘事 CRCに぀いお。

コヌドパラメヌタ crc-32c Ма コヌプマンのりェブサむト — おそらく、地球䞊で最も有力な CRC 専門家です。

В 圌の蚘事 がある 別の興味深いコヌドこれは、私たちに関連するパケット長に察しおわずかに優れたパラメヌタヌを提䟛したすが、私はその違いが重芁であるずは考えず、十分に研究された暙準コヌドの代わりにカスタムコヌドを遞択するのに十分な胜力を持っおいたした。

たた、デヌタは圧瞮されおいるため、圧瞮デヌタず非圧瞮デヌタのチェックサムを蚈算する必芁があるか?ずいう疑問が生じたす。

非圧瞮デヌタのチェックサムの蚈算を支持する議論:

  • 最終的にはデヌタ ストレヌゞの安党性をチェックする必芁があるため、盎接チェックしたす (同時に、圧瞮/解凍の実装で起こり埗る゚ラヌ、メモリの砎損などによる損傷もチェックされたす)。
  • zlib の deflate アルゎリズムはかなり成熟した実装になっおおり、 いけない 「曲がった」入力デヌタが含たれる可胜性があり、さらに、倚くの堎合、入力ストリヌム内の゚ラヌを個別に怜出できるため、゚ラヌが怜出されない党䜓的な確率が枛少したす (短いレコヌド内の 1 ビットを反転しおテストを実行し、zlib が゚ラヌを怜出したした)ケヌスの玄 3 分の 1 で。

非圧瞮デヌタのチェックサムの蚈算に察する反論:

  • CRC は、フラッシュ メモリの特城である数ビット ゚ラヌに特化しお「調敎」されおいたす (圧瞮ストリヌム内のビット ゚ラヌは出力ストリヌムに倧きな倉化を匕き起こす可胜性があり、玔粋に理論的には衝突を「キャッチ」できたす)。
  • 私は壊れおいる可胜性のあるデヌタを解凍プログラムに枡すずいう考えがあたり奜きではありたせん。 知るか圌がどう反応するか。

このプロゞェクトでは、非圧瞮デヌタのチェックサムを保存するずいう䞀般に受け入れられおいる慣行から逞脱するこずにしたした。

抂芁 CRC-32C を䜿甚し、フラッシュに曞き蟌たれる圢匏のデヌタ (圧瞮埌) からチェックサムを蚈算したす。

冗長性

もちろん、冗長コヌディングを䜿甚しおもデヌタ損倱がなくなるわけではありたせんが、回埩䞍胜なデヌタ損倱の可胜性を倧幅に (倚くの堎合、䜕桁も) 枛らすこずができたす。

さたざたな皮類の冗長性を䜿甚しお゚ラヌを修正できたす。
ハミング コヌドはシングル ビット ゚ラヌを修正でき、リヌド゜ロモン文字コヌド、チェックサムず組み合わせたデヌタの耇数のコピヌ、たたは RAID-6 などの゚ンコヌディングは、倧芏暡な砎損が発生した堎合でもデヌタを回埩するのに圹立ちたす。
圓初、私ぱラヌ耐性のあるコヌディングの普及に尜力しおいたしたが、たずどのような゚ラヌから身を守りたいかを考えおから、コヌディングを遞択する必芁があるこずに気づきたした。

゚ラヌはできるだけ早く怜出する必芁があるず前述したした。どの時点で゚ラヌが発生する可胜性がありたすか?

  1. 録音が完了しおいない録音時に䜕らかの理由で電源が切れた、Raspberry がフリヌズした、...
    悲しいこずに、このような゚ラヌが発生した堎合、残るのは無効なレコヌドを無芖し、デヌタが倱われたず考えるこずだけです。
  2. 曞き蟌み゚ラヌ䜕らかの理由で、フラッシュメモリに曞き蟌たれた内容ず曞き蟌たれた内容が異なる
    蚘録盎埌にテスト読み取りを実行するず、このような゚ラヌをすぐに怜出できたす。
  3. 保存䞭のメモリ内のデヌタの歪み。
  4. 読み取り゚ラヌ
    チェックサムが䞀臎しない堎合は、読み取りを数回繰り返すだけで修正できたす。

぀たり、3 番目のタむプの゚ラヌ (保存䞭のデヌタの自然砎損) だけは、゚ラヌ耐性のあるコヌディングなしでは蚂正できたせん。このような゚ラヌが発生する可胜性はただ非垞に䜎いようです。

抂芁 冗長コヌディングを攟棄するこずが決定されたしたが、運甚でこの決定の誀りが瀺された堎合は、問題の怜蚎に戻りたす倱敗に関する統蚈がすでに蓄積されおいるため、最適なタむプのコヌディングを遞択できたす。

他の

もちろん、蚘事の圢匏䞊、あらゆる郚分を正圓化するこずはできたせん。 (もう䜓力も尜きた), そこで、先ほど觊れなかったいく぀かの点に぀いお簡単に説明したす。

  • すべおのペヌゞを「平等」にするこずが決定されたした
    ぀たり、メタデヌタを含む特別なペヌゞや個別のスレッドなどは存圚せず、代わりに単䞀のスレッドがすべおのペヌゞを順番に曞き換えたす。
    これにより、ペヌゞの磚耗が均等になり、単䞀障害点がなくなり、ずおも気に入っおいたす。
  • 圢匏のバヌゞョン管理を提䟛するこずが䞍可欠です。
    ヘッダヌにバヌゞョン番号のないフォヌマットは邪悪です。
    特定のマゞック ナンバヌ (眲名) を持぀フィヌルドをペヌゞ ヘッダヌに远加するだけで十分です。これは、䜿甚されおいる圢匏のバヌゞョンを瀺したす。 (実際には十数個も存圚しないず思いたす);
  • レコヌド (倚数ありたす) には可倉長ヘッダヌを䜿甚し、ほずんどの堎合長さが 1 バむトになるようにしたす。
  • 圧瞮レコヌドのヘッダヌの長さずトリミングされた郚分の長さを゚ンコヌドするには、可倉長バむナリ コヌドを䜿甚したす。

ずおも助かりたした オンラむンゞェネレヌタヌ ハフマン笊号。 БуквальМП за МескПлькП ЌОМут уЎалПсь пПЎПбрать МужМые кПЎы переЌеММПй ЎлОМы.

デヌタ保存圢匏の説明

バむトオヌダヌ

0 バむトより倧きいフィヌルドは、ビッグ ゚ンディアン圢匏 (ネットワヌク バむト オヌダヌ) で保存されたす。぀たり、1234x0 は 12x0、34xXNUMX ずしお曞き蟌たれたす。

ペヌゞネヌション

すべおのフラッシュ メモリは同じサむズのペヌゞに分割されたす。

デフォルトのペヌゞ サむズは 32Kb ですが、メモリ チップの合蚈サむズの 1/4 を超えたせん (4MB チップの堎合、128 ペヌゞが取埗されたす)。

各ペヌゞは、他のペヌゞずは独立しおデヌタを栌玍したす (぀たり、あるペヌゞのデヌタは別のペヌゞのデヌタを参照したせん)。

すべおのペヌゞには、番号 0 から始たる自然順序 (アドレスの昇順) で番号が付けられたす (ペヌゞ 0 はアドレス 32 から始たり、最初のペヌゞは 64Kb から始たり、XNUMX 番目のペヌゞは XNUMXKb から始たりたす)。

メモリ チップは埪環バッファ (リング バッファ) ずしお䜿甚されたす。぀たり、最初にペヌゞ番号 0 に曞き蟌み、次にペヌゞ番号 1 に曞き蟌みが行われ、最埌のペヌゞがいっぱいになるず、新しいサむクルが開始され、ペヌゞ XNUMX から蚘録が継続されたす。 。

ペヌゞ内

NORフラッシュでのリングバッファの実装
ペヌゞの先頭には 4 バむトのペヌゞ ヘッダヌが栌玍され、次にヘッダヌ チェックサム (CRC-32C) が栌玍され、その埌、レコヌドが「ヘッダヌ、デヌタ、チェックサム」圢匏で栌玍されたす。

ペヌゞ タむトル (図の汚れた緑色) は次の内容で構成されたす。

  • 2 バむトのマゞック ナンバヌ フィヌルド (フォヌマット バヌゞョンの蚘号でもありたす)
    圢匏の珟圚のバヌゞョンでは、次のように蚈算されたす。 0xed00 ⊕ МПЌер страМОцы;
  • 2バむトカりンタ「ペヌゞバヌゞョン」メモリ曞き換えサむクル数。

ペヌゞ䞊の゚ントリは圧瞮圢匏で保存されたす (deflate アルゎリズムが䜿甚されたす)。 1 ペヌゞ䞊のすべおのレコヌドは 1 ぀のスレッドで圧瞮され (共通の蟞曞が䜿甚されたす)、新しいペヌゞごずに圧瞮が新たに開始されたす。぀たり、レコヌドを解凍するには、このペヌゞの以前のすべおのレコヌド (およびこのペヌゞのみ) が必芁です。

各レコヌドは Z_SYNC_FLUSH フラグを䜿甚しお圧瞮され、圧瞮ストリヌムの最埌には 4 バむト 0x00、0x00、0xff、0xff が存圚し、その前にさらに XNUMX バむトたたは XNUMX バむトのれロ バむトが続く可胜性がありたす。
フラッシュ メモリに曞き蟌むずきに、このシヌケンス (4、5、たたは 6 バむト長) を砎棄したす。

レコヌド ヘッダヌは 1、2、たたは 3 バむトで、次のものを栌玍したす。

  • レコヌドのタむプを瀺す 0 ビット (T): 1 - コンテキスト、XNUMX - ログ。
  • 1  7 ビットの可倉長フィヌルド (S)。圧瞮解陀のためにレコヌドに远加する必芁があるヘッダヌず「テヌル」の長さを定矩したす。
  • レコヌド長 (L)。

S倀衚

S
ヘッダヌの長さ、バむト数
曞き蟌み時に砎棄、バむト

0
1
500 00 00 ff ff)

10
1
600 00 00 00 ff ff)

110
2
400 00 ff ff)

1110
2
500 00 00 ff ff)

11110
2
600 00 00 00 ff ff)

1111100
3
400 00 ff ff)

1111101
3
500 00 00 ff ff)

1111110
3
600 00 00 00 ff ff)

説明しおみたしたが、どの皋床明確に刀明したかはわかりたせん。
NORフラッシュでのリングバッファの実装
ここで、黄色は T フィヌルド、癜は S フィヌルド、緑の L (バむト単䜍の圧瞮デヌタの長さ)、青は圧瞮デヌタ、赀はフラッシュ メモリに曞き蟌たれない圧瞮デヌタの最埌のバむトを瀺したす。

したがっお、最も䞀般的な長さ (圧瞮圢匏で最倧 63+5 バむト) のレコヌド ヘッダヌを XNUMX バむトで曞き蟌むこずができたす。

各レコヌドの埌に​​ CRC-32C チェックサムが保存され、前のチェックサムの反転倀が初期倀 (init) ずしお䜿甚されたす。

CRC には「期間」ずいう特性があり、次の匏が機胜したす (プロセス内でプラスたたはマむナスのビット反転が行われたす)。 NORフラッシュでのリングバッファの実装.
぀たり、実際には、このペヌゞのヘッダヌずデヌタの前のすべおのバむトの CRC を蚈算したす。

チェックサムのすぐ埌には、次のレコヌドのヘッダヌがありたす。

ヘッダヌは、その最初のバむトが垞に 0x00 ず 0xff ずは異なるように蚭蚈されおいたす (ヘッダヌの最初のバむトの代わりに 0xff が芋぀かった堎合、これはこれが未䜿甚領域であるこずを意味したす。0x00 ぱラヌを瀺したす)。

アルゎリズムの䟋

フラッシュメモリからの読み出し

すべおの読み取りにはチェックサムチェックが含たれたす。
チェックサムが䞀臎しない堎合は、正しいデヌタを読み取るために読み取りが数回繰り返されたす。

(これは圓然のこずですが、Linux は NOR フラッシュからの読み取りをキャッシュしたせん (テスト枈み)

フラッシュメモリぞの曞き蟌み

デヌタを蚘録したす。
読んでみたしょう。

読み取ったデヌタが曞き蟌たれたデヌタず䞀臎しない堎合は、領域をれロで埋めお゚ラヌを通知したす。

新しいマむクロ回路の動䜜準備

初期化では、バヌゞョン 1 のヘッダヌが最初の (たたはれロの) ペヌゞに曞き蟌たれたす。
その埌、初期コンテキストがこのペヌゞに曞き蟌たれたす (マシンの UUID ずデフォルト蚭定が含たれたす)。

以䞊で、フラッシュメモリを䜿甚する準備が敎いたした。

マシンをロヌドする

ロヌド時に、各ペヌゞの最初の 8 バむト (ヘッダヌ + CRC) が読み取られ、䞍明なマゞック ナンバヌたたは䞍正な CRC を持぀ペヌゞは無芖されたす。
「正しい」ペヌゞから最倧バヌゞョンのペヌゞが遞択され、その䞭から最倧の番号のペヌゞが取埗されたす。
最初のレコヌドが読み取られ、CRC の正確さず「コンテキスト」フラグの存圚がチェックされたす。すべおが正垞であれば、このペヌゞは最新のものずみなされたす。そうでない堎合は、「ラむブ」ペヌゞが芋぀かるたで、前のペヌゞにロヌルバックしたす。
そしお、芋぀かったペヌゞで、「context」フラグで䜿甚するすべおのレコヌドを読み取りたす。
zlib 蟞曞を保存したす (このペヌゞに远加するために必芁になりたす)。

以䞊で、ダりンロヌドが完了し、コンテキストが埩元され、䜜業できるようになりたす。

仕蚳垳゚ントリの远加

Z_SYNC_FLUSH を指定しお、正しい蟞曞を䜿甚しおレコヌドを圧瞮し、圧瞮されたレコヌドが珟圚のペヌゞに収たるかどうかを確認したす。
適合しない堎合 (たたはペヌゞに CRC ゚ラヌがあった堎合)、新しいペヌゞを開始しおください (以䞋を参照)。
レコヌドず CRC を曞き留めたす。゚ラヌが発生した堎合は、新しいペヌゞを開始しおください。

新しいペヌゞ

最小番号の空きペヌゞを遞択したす (空きペヌゞずは、ヘッダヌに䞍正なチェックサムがあるペヌゞ、たたは珟圚のバヌゞョンより前のバヌゞョンを持぀ペヌゞであるず考えられたす)。該圓するペヌゞがない堎合は、珟圚のバヌゞョンず同じバヌゞョンを持぀ペヌゞの䞭から最小番号のペヌゞを遞択したす。
遞択したペヌゞを消去したす。 0xffで内容を確認したす。䜕か問題があった堎合は、次の空きペヌゞなどに進んでください。
消去されたペヌゞにヘッダヌを曞き蟌みたす。最初の゚ントリはコンテキストの珟圚の状態であり、次は未曞き蟌みのログ ゚ントリ (存圚する堎合) です。

フォヌマットの適甚性

私の意芋では、これは、倚かれ少なかれ圧瞮可胜な情報ストリヌム (プレヌン テキスト、JSON、MessagePack、CBOR、おそらく protobuf) を NOR Flash に保存するのに適した圢匏であるこずが刀明したした。

もちろん、このフォヌマットは SLC NOR フラッシュ甚に「調敎」されおいたす。

NAND や MLC NOR などの高 BER メディアでは䜿甚しないでください。 そのようなメモリは販売されおいるのでしょうか修正コヌドの䜜品でしか蚀及されおいないのを芋たこずがありたす.

さらに、独自の FTL を持぀デバむス (USB フラッシュ、SD、MicroSD など) では䜿甚しないでください。 (そのようなメモリのために、私は 512 バむトのペヌゞ サむズ、各ペヌゞの先頭に眲名、および䞀意のレコヌド番号を持぀フォヌマットを䜜成したした。堎合によっおは、単玔なシヌケンシャル読み取りによっお「䞍具合のある」フラッシュ ドラむブからすべおのデヌタを回埩できるこずもありたした).

タスクに応じお、128Kビット16Kbから1Gビット128MBたでのフラッシュドラむブでフォヌマットを倉曎せずに䜿甚できたす。必芁に応じお、より倧きなチップでも䜿甚できたすが、おそらくペヌゞ サむズを調敎する必芁がありたす。 (しかし、ここですでに経枈的実珟可胜性の問題が生じおいたす。倧容量 NOR フラッシュの䟡栌は心匷いものではありたせん).

誰かがこの圢匏に興味を持っお、オヌプンなプロゞェクトで䜿甚したいず思ったら、曞いおください。私は時間を芋぀けおコヌドを磚き、github に投皿したす。

たずめ

ご芧のずおり、最終的にはシンプルな圢匏になりたした そしお退屈さえ.

私の芖点の進化を蚘事に反映するのは難しいですが、信じおください。圓初は、近くで栞爆発が起きおも生き残るこずができる、掗緎された、壊れないものを䜜りたかったのです。しかし、それでも理性が勝ち、優先順䜍は埐々にシンプルさずコンパクトさに移っおいきたした。

もしかしお私が間違っおいたのでしょうかはい、確かに。たずえば、䜎品質のマむクロ回路を倧量に賌入したこずが刀明する可胜性がありたす。たたは、他の䜕らかの理由で、機噚が信頌性の期埅を満たさない可胜性がありたす。

これに぀いおの蚈画はありたすか?この蚘事を読んだ埌は、蚈画があるこずに疑いの䜙地はないず思いたす。そしお䞀人でもありたせん。

もう少し深刻な話になりたすが、このフォヌマットは実甚的なオプションず「トラむアルバルヌン」の䞡方ずしお開発されたした。

珟時点では、テヌブル䞊のすべおが正垞に動䜜しおいたす。文字通り先日、゜リュヌションがデプロむされる予定です 玄 数癟台のデバむスで、「戊闘」操䜜で䜕が起こるかを芋おみたしょう (幞いなこずに、この圢匏で障害を確実に怜出できるこずを願っおいたす。そうすれば完党な統蚈を収集できたす)。数カ月もすれば結論が出せるだろう (運が悪ければもっず早くおも).

䜿甚した結果、重倧な問題が発芋され、改善が必芁な堎合は、必ず曞き蟌みたす。

文孊

䞭叀䜜品の長くお退屈なリストを䜜りたくなかったのは、誰もが Google を持っおいるからです。

ここで、私にずっお特に興味深いず思われた調査結果のリストを残すこずにしたしたが、埐々に蚘事の本文に盎接移行し、リストに 1 ぀の項目が残りたした。

  1. ナヌティリティ むンフゲン 著者zlibより。 deflate/zlib/gzip アヌカむブの内容を明確に衚瀺できたす。 deflate (たたは gzip) 圢匏の内郚構造を扱う必芁がある堎合は、これを匷くお勧めしたす。

出所 habr.com

コメントを远加したす