高放射性環境で使用するためのアプリケーションのコンパイル


1456

私たちは、電離放射線の衝撃を受けた環境のシールドされたデバイスに導入された組み込みC / C ++アプリケーションをコンパイルしています。ARM向けにGCCとクロスコンパイルを使用しています。デプロイすると、アプリケーションが誤ったデータを生成し、予想よりも頻繁にクラッシュします。ハードウェアはこの環境用に設計されており、アプリケーションはこのプラットフォームで数年間実行されています。

コードに加えることができる変更、または単一イベントの混乱によって引き起こされるソフトエラーとメモリ破損を特定/修正するために実行できるコンパイル時の改善はありますか?他の開発者は、長期実行アプリケーションでのソフトエラーの悪影響を軽減することに成功しましたか?


186
メモリの値が変化していますか、それともプロセッサの値が変化していますか?ハードウェアが環境用に設計されている場合、ソフトウェアは非放射性環境で実行されているかのように実行する必要があります。
Thomas Matthews

3
可能であれば、放射に耐性のある不揮発性メモリにイベントを保存するロギングシステムをセットアップする必要があります。イベントを追跡し、根本的な原因を簡単に見つけられるように、十分な情報を保存します。
Thomas Matthews

2
@Thomas MatthewsすべてのメモリにはFITエラー率があり、ハードウェアメーカーは多くの約束をしています。ほとんどの問題は、実行時にRAMを変更するSEUが原因である可能性があります。
ルーク

9
これはハードウェア/ソフトウェアの組み合わせソリューションですが、テキサスインスツルメンツ(およびおそらく他のソリューション)は、2つの重複コアで構成され、ロックステップで動作し、クロックサイクルの半分の位相がずれている安全性が重要なアプリケーション向けの組み込みチップを作成しています。ハードウェアがコア間で異なるものを検出したときに実行される特別な割り込みとリセットアクションがあるため、エラーから回復できます。TIはそれらを「Hercules」セーフティプロセッサとしてブランド化していると思います。
mbrig 2017年

5
冗長な頑丈なモーター、一部のギア、シャフト、ラチェット!線量率に応じて、毎年またはより頻繁に交換してください。いいえ、実際、これらの種類の問題に対する私の最初の質問は常にありました。そこに多くのソフトウェアが本当に必要ですか できる限りアナログを使いましょう。
jwdonahue

回答:


814

小型衛星のソフトウェア/ファームウェア開発と環境テストで約4〜5年間働いて*、ここで私の経験を共有したいと思います。

*(小型化された衛星は、電子コンポーネントのサイズが比較的小さく制限されているため、大型の衛星よりもシングルイベントの混乱が発生しやすい

非常に簡潔かつ直接的である:から回復するメカニズムがない、検出、誤った状況ソフトウェアによっては/自分自身をファームウェアせずに、少なくとも、1つの、 コピー最小作業バージョンのソフトウェア/ファームウェアのどこかのための回復 -とで目的のハードウェアをサポート回復(機能)。

現在、この状況は通常、ハードウェアレベルとソフトウェアレベルの両方で処理されます。ここでは、ご要望に応じて、ソフトウェアレベルで実行できることを共有します。

  1. ...回復目的...。実際の環境でソフトウェア/ファームウェアを更新/再コンパイル/再フラッシュする機能を提供します。これは、高度にイオン化された環境にあるすべてのソフトウェア/ファームウェアでほぼ必須の機能です。これがないと、必要な数の冗長ソフトウェア/ハードウェアを使用できますが、ある時点で、それらはすべて破壊されます。それで、この機能を準備してください!

  2. ...最低限の作業バージョン...応答性の高い、複数のコピー、ソフトウェア/ファームウェアの最低バージョンをコードに含めます。これは、Windowsのセーフモードに似ています。ソフトウェアの完全に機能するバージョンを1つだけ持つのではなく、ソフトウェア/ファームウェアの最小バージョンのコピーを複数用意します。最小コピーは通常、フルコピーよりサイズがはるかに小さく、ほとんどの場合、次の2つまたは3つの機能しかありません。

    1. 外部システムからのコマンドを聞くことができる、
    2. 現在のソフトウェア/ファームウェアを更新できる
    3. 基本操作のハウスキーピングデータを監視できます。
  3. ...コピー...どこかに...冗長ソフトウェア/ファームウェアをどこかに持っています。

    1. 冗長ハードウェアの有無にかかわらず、ARM uCに冗長ソフトウェア/ファームウェアを搭載することができます。これは通常、互いにハートビートを送信する別々のアドレスに 2つ以上の同一のソフトウェア/ファームウェアを置くことによって行われますが、一度にアクティブになるのは1つだけです。1つ以上のソフトウェア/ファームウェアが応答しないことがわかっている場合は、他のソフトウェア/ファームウェアに切り替えます。このアプローチを使用する利点は、エラーが発生した直後に機能を交換できることです。エラーの検出と修復を担当する外部システム/関係者に連絡する必要はありません(衛星の場合、通常はMission Control Center( MCC))。

      厳密に言えば、冗長ハードウェアがないと、これを行うことの欠点は、実際にすべての単一障害点を排除できないことです。少なくとも、まだ1つはありますである単一障害点、スイッチ自体(多くの場合、またはコードの先頭に)。それでも、高度にイオン化された環境(ピコ/フェムト衛星など)でサイズが制限されているデバイスでは、ハードウェア追加せずに単一障害点を1点に削減することを検討する価値があります。さらに、切り替え用のコードは、プログラム全体のコードよりもはるかに少ないため、シングルイベントが発生するリスクが大幅に軽減されます。

    2. ただし、これを行わない場合は、外部システムに少なくとも1つのコピーが必要です。これは、デバイスと接触し、ソフトウェア/ファームウェアを更新できます(サテライトの場合も、ミッションコントロールセンターです)。

    3. 実行中のシステムのソフトウェア/ファームウェアを復元するためにトリガーできるデバイスの永続的なメモリストレージにコピーを置くこともできます
  4. ...検出可能なエラー状態。エラーは通常、ハードウェアエラー修正/検出回路またはエラー修正/検出用の小さなコードによって検出可能でなければなりません。そのようなコードは小さく、複数で、独立したものにするのが最善です、メインのソフトウェア/ファームウェアからです。その主なタスクは、チェック/修正のみです。ハードウェア回路/ファームウェアが信頼できる場合(他のものよりも耐放射線性が高い、または複数の回路/ロジックがあるなど)、それを使用してエラー修正を行うことを検討する場合があります。しかし、そうでない場合は、エラー検出として作成することをお勧めします。修正は、外部システム/デバイスによって行うことができます。エラー訂正については、回路/ソフトウェアの両方でより簡単に実装できるため、Hamming / Golay23のような基本的なエラー訂正アルゴリズムの使用を検討できます。しかし、それは最終的にはチームの能力に依存します。エラー検出には、通常CRCが使用されます。

  5. ...回復をサポートするハードウェア今、この問題で最も困難な側面になります。結局のところ、回復には、回復に関与するハードウェアが少なくとも機能している必要があります。ハードウェアが恒久的に破損している場合(通常、総イオン化線量が特定のレベルに達した後に発生します)、ソフトウェアが回復を支援する方法は(悲しいことに)ありません。したがって、ハードウェアは、高い放射線レベルにさらされるデバイス(衛星など)にとって最も重要な関心事です。

上記の単一イベントの混乱によるファームウェアのエラーを予測するための提案に加えて、私はあなたに次のことを勧めたいと思います:

  1. サブシステム間通信プロトコルのエラー検出および/またはエラー訂正アルゴリズム。これは、他のシステムから受信した不完全な/間違った信号を回避するためにほぼ必要なもう1つの方法です。

  2. ADCの読み取り値をフィルタリングします。ADCの読み取り値を直接使用しないでください。中央値フィルター、平均フィルター、またはその他のフィルターでフィルターします- 単一の読み取り値を信頼しないでください。より多くではなく、より多くのサンプルを-合理的に。


401

NASAは耐放射線ソフトウェアに関する論文を持ってます。3つの主要なタスクについて説明します。

  1. メモリのエラーを定期的に監視し、それらのエラーを除去します。
  2. 堅牢なエラー回復メカニズム、および
  3. 何かが機能しなくなった場合に再構成する機能。

ほとんどのECCメモリはマルチビットエラーではなくシングルビットエラーから回復できるため、メモリスキャンレートはマルチビットエラーがほとんど発生しない頻度である必要があります。

堅牢なエラー回復には、制御フロー転送(通常、エラーの前の時点でプロセスを再開する)、リソースの解放、およびデータの復元が含まれます。

データの復元に関する主な推奨事項は、中間データを一時的なものとして扱い、エラーが発生する前に再起動してもデータが信頼できる状態にロールバックされるようにすることで、その必要性を回避することです。これは、データベースの「トランザクション」の概念に似ています。

彼らは、C ++などのオブジェクト指向言語に特に適した手法について説明します。例えば

  1. 隣接するメモリオブジェクト用のソフトウェアベースのECC
  2. 契約によるプログラミング:前提条件と事後条件を確認し、オブジェクトをチェックして、オブジェクトがまだ有効な状態であることを確認します。

そして、それはたまたま起こり、NASAは火星探査車のような主要なプロジェクトにC ++を使用しました。

C ++クラスの抽象化とカプセル化により、複数のプロジェクトと開発者間での迅速な開発とテストが可能になりました。

問題を引き起こす可能性がある特定のC ++機能を回避しました。

  1. 例外
  2. テンプレート
  3. Iostream(コンソールなし)
  4. 多重継承
  5. 演算子の過負荷(newおよび以外)delete
  6. 動的割り当て(newシステムヒープの破損の可能性を回避するために専用のメモリプールと配置を使用)。

28
これは実際、純粋な言語が得意なもののように聞こえます。値は変更されないため、破損した場合は元の定義に戻ることができ(本来の設定です)、誤って同じことを2回行うことはありません(副作用がないため)。
PyRulez

20
RAIIは悪い考えです。それが正しく機能するか、まったく機能しないかに依存することができないためです。データなどにランダムに損傷を与える可能性があります。実際には、できるだけ多くの不変性と、それに加えてエラー修正メカニズムが必要です。壊れたものを捨てる方が、どうにかして修理するよりもはるかに簡単です(どのようにして正確に古い状態に戻るのに十分なことがわかりますか?)。ただし、これにはかなり愚かな言語を使用する必要があります。
Luaan

67
@PyRulez:純粋な言語は抽象概念であり、ハードウェアは純粋ではありません。コンパイラーはその違いを隠すのが得意です。プログラムがステップXの後で論理的に使用すべきではない値を持っている場合、コンパイラーはステップX + 1で計算された値で上書きする可能性があります。しかし、これは戻ることができないことを意味します。より正式には、純粋な言語でのプログラムの可能な状態は非循環グラフを形成します。つまり、2つの状態は同等であり、両方から到達可能な状態が同等である場合にマージできます。この合併により、これらの州に至る道の違いがなくなります。
MSalters

2
@Vorac-プレゼンテーションによると、C ++テンプレートに関する懸念はコードの膨張です。
jww

3
@DeerSpotter正確な問題はそれよりもはるかに大きなものです。イオン化は、実行中のウォッチャープログラムの一部を損傷する可能性があります。次に、ウォッチャーのウォッチャーが必要です。次に、ウォッチャーのウォッチャーのウォッチャーなどが必要になります...
Agnius Vasiliauskas

116

ここにいくつかの考えやアイデアがあります:

ROMをより創造的に使用します。

できる限りROMに保存します。物事を計算する代わりに、ルックアップテーブルをROMに保存します。(コンパイラがルックアップテーブルを読み取り専用セクションに出力していることを確認してください。実行時にメモリアドレスを出力して確認してください!)割り込みベクターテーブルをROMに保存します。もちろん、いくつかのテストを実行して、ROMとRAMの信頼性を比較してください。

スタックには最高のRAMを使用してください。

スタック内のSEUはおそらくインデックス変数、ステータス変数、戻りアドレス、さまざまな種類のポインタなどが存在する場所であるため、おそらくクラッシュの最も可能性の高いソースです。

タイマーティックおよびウォッチドッグタイマールーチンを実装します。

タイマー刻みごとに「健全性チェック」ルーチンを実行できるだけでなく、システムのロックアップを処理するウォッチドッグルーチンも実行できます。メインコードは定期的にカウンターをインクリメントして進行状況を示し、正常性チェックルーチンはこれが発生したことを確認できます。

ソフトウェアにエラー修正コードを実装します

エラーを検出および/または修正できるように、データに冗長性を追加できます。これにより、処理時間が長くなり、プロセッサが長時間放射線にさらされたままになる可能性があるため、エラーの可能性が高まるため、トレードオフを考慮する必要があります。

キャッシュを覚えておいてください。

CPUキャッシュのサイズを確認します。最近アクセスまたは変更したデータは、おそらくキャッシュ内にあります。少なくとも一部のキャッシュを無効にできる(パフォーマンスコストが大きい)と思います。これを試して、キャッシュがSEUに対してどれほど影響を受けやすいかを確認してください。キャッシュがRAMよりも硬い場合は、重要なデータを定期的に読み取りおよび再書き込みして、キャッシュに確実に留まり、RAMを正常な状態に戻すことができます。

ページフォルトハンドラーを巧みに使用してください。

メモリページを存在しないものとしてマークすると、CPUはアクセスしようとしたときにページフォールトを発行します。読み取りリクエストを処理する前にチェックを行うページフォールトハンドラーを作成できます。(PCオペレーティングシステムはこれを使用して、ディスクにスワップされたページを透過的にロードします。)

重要なもの(すべての場合もあります)にはアセンブリ言語を使用します。

アセンブリ言語を使用すると、レジスタとRAMの内容がわかります。CPUが使用しいる特別なRAMテーブルがわかっているので、リスクを低く抑えるために回り道で物事を設計できます。

objdump生成されたアセンブリ言語を実際に調べて、各ルーチンが占めるコードの量を計算するために使用します。

Linuxのような大きなOSを使用している場合は、問題が発生します。非常に複雑で、うまくいかないことがたくさんあります。

それは確率のゲームであることを忘れないでください。

コメント者は言った

エラーをキャッチするために作成するすべてのルーチンは、同じ原因から失敗する可能性があります。

これは事実ですが、チェックルーチンが正しく機能するために必要な(たとえば)100バイトのコードとデータでのエラーの可能性は、他の場所でのエラーの可能性よりもはるかに小さくなります。ROMがかなり信頼でき、ほとんどすべてのコード/データが実際にROMにある場合、オッズはさらに良くなります。

冗長ハードウェアを使用します。

同じコードで2つ以上の同じハードウェアセットアップを使用します。結果が異なる場合は、リセットをトリガーする必要があります。3つ以上のデバイスでは、「投票」システムを使用して、侵害されたデバイスを特定することができます。


14
最近では、ハードウェアを介して利用できるECCがあり、処理時間を節約できます。ステップ1は、ECCが組み込まれたマイクロコントローラーを選択することです。
ランディン

23
私の心のどこかに、アビオニクス(おそらくスペースシャトル?)のフライトハードウェアへの参照があります。この場合、冗長アーキテクチャは同一ではないように(そして異なるチームによって)明示的に設計されました。これにより、ハードウェア/ソフトウェア設計のシステムエラーの可能性が軽減され、同じ入力に直面したときにすべての投票システムが同時にクラッシュする可能性が減少します。
Peter M

8
@PeterM:ボーイング777のフライトソフトウェアにも使用されているAFAIK:3つのプログラミング言語による3つのチームによる3つのバージョン。
モニカの復活-M.シュローダー

7
@DanEsparza RAMは通常、データを保存するフィードバック(SRAM)にコンデンサ(DRAM)またはいくつかのトランジスタを備えています。放射イベントにより、コンデンサが誤って充電/放電されたり、フィードバックループの信号が変化したりする可能性があります。ROMは、通常、(少なくとも特別な状況やより高い電圧なしで)書き込む機能を必要としないため、物理レベルで本質的に安定している可能性があります。
nanofarad

7
@DanEsparza:ROMメモリには複数のタイプがあります。「ROM」がeepromまたはflash readonly-at-5vでプログラム可能であるが、-10vでエミュレートされている場合、「ROM」はまだイオン化されている傾向があります。たぶん他より少ない。ただし、マスクROMヒューズベースのPROMなどの古いハードコアのものはありますが、失敗するまでにはかなりの量の放射線が必要になると思います。ただし、まだ製造されているかどうかはわかりません。
ケツァルコアトル2016

105

また、アルゴリズムフォールトトレランスのテーマに関する豊富な資料に興味があるかもしれません。これには、古い割り当てが含まれます。一定数の比較が失敗する場合に入力を正しくソートするソートを記述します(または、失敗した比較の漸近数が比較のようにスケーリングする場合は、少し邪魔なバージョンlog(n)ですn)。

読み始める場所は、黄とアブラハムの1984年の論文です。 " Matrix Operations for Algorithm Operationsのためのアルゴリズムベースのフォールトトレランス」です。彼らの考えは、準同型暗号化計算と漠然と似ています(ただし、操作レベルでエラーの検出/修正を試みているため、実際には同じではありません)。

その論文のより最近の子孫は、Bosilca、Delmas、Dongarra、およびLangouの「高性能コンピューティングに適用されるアルゴリズムベースのフォールトトレランス」です。


5
私はあなたの反応が本当に好きです。これは、データの整合性に対するより一般的なソフトウェアアプローチであり、アルゴリズムベースのフォールトトレランスソリューションが最終製品で使用されます。ありがとう!
2016年

41

放射性環境用のコードを書くことは、ミッションクリティカルなアプリケーション用のコードを書くこととまったく同じです。

既に言及されていることに加えて、いくつかの雑多なヒントがあります:

  • セミプロの組み込みシステムに必要な日常の「パンとバター」の安全対策を使用してください:内部ウォッチドッグ、内部低電圧検出、内部クロックモニター。これらは2016年にも言及する必要はなく、ほとんどすべての最新のマイクロコントローラーで標準となっています。
  • 安全および/または自動車向けのMCUを使用している場合、ウォッチドッグをリフレッシュする必要のある特定の時間枠など、特定のウォッチドッグ機能があります。これは、ミッションクリティカルなリアルタイムシステムがある場合に推奨されます。
  • 一般に、これらのシステムに適したMCUを使用してください。コーンフレークのパケットで受け取った一般的な主流の綿毛は使用しないでください。現在、ほぼすべてのMCUメーカーが安全アプリケーション(TI、フリースケール、ルネサス、ST、インフィニオンなど)向けに設計された専用MCUを持っています。これらには、ロックステップコアを含む多くの組み込みの安全機能があります。つまり、同じコードを実行する2つのCPUコアがあり、それらは互いに一致する必要があります。
  • 重要:内部MCUレジスタの整合性を確保する必要があります。書き込み可能なハードウェア周辺機器のすべての制御およびステータスレジスタは、RAMメモリに配置されている可能性があるため、脆弱です。

    レジスタの破損から身を守るために、できればレジスタの「追記型」機能が組み込まれたマイクロコントローラを選択してください。さらに、すべてのハードウェアレジスタのデフォルト値をNVMに格納し、それらの値を定期的にレジスタにコピーする必要があります。同様に、重要な変数の整合性を確保できます。

    注:常に防御的プログラミングを使用してください。つまり、アプリケーションで使用されるレジスタだけでなく、MCU内のすべてのレジスタをセットアップする必要があります。ランダムなハードウェアペリフェラルが突然起動したくない場合。

  • RAMまたはNVMのエラーをチェックする方法はすべてあります。チェックサム、「ウォーキングパターン」、ソフトウェアECCなどです。現在のところ、これらのいずれも使用せずに、組み込みのECCを備えたMCUおよび同様のチェック。ソフトウェアでこれを行うのは複雑であり、エラーチェック自体がバグや予期しない問題を引き起こす可能性があるためです。

  • 冗長性を使用します。揮発性メモリと不揮発性メモリの両方を、常に同等である必要がある2つの同一の「ミラー」セグメントに格納できます。各セグメントにはCRCチェックサムを添付できます。
  • MCUの外部にある外部メモリの使用を避けます。
  • すべての可能な割り込み/例外のデフォルトの割り込みサービスルーチン/デフォルトの例外ハンドラーを実装します。使っていないものでも。デフォルトのルーチンは、独自の割り込みソースを遮断する以外は何もすべきではありません。
  • 防御的プログラミングの概念を理解して受け入れる。つまり、プログラムは、理論的には発生し得ないものも含め、すべての可能なケースを処理する必要があります。

    高品質のミッションクリティカルなファームウェアは、できるだけ多くのエラーを検出し、安全な方法でそれらを無視します。

  • 仕様が不十分な動作に依存するプログラムを作成しないでください。そのような動作は、放射またはEMIによって引き起こされる予期しないハードウェアの変更によって大幅に変化する可能性があります。プログラムにそのようながらくたがないことを保証する最良の方法は、MISRAなどのコーディング標準を静的アナライザーツールとともに使用することです。これは、防御的プログラミングやバグの除去にも役立ちます(どのような種類のアプリケーションでもバグを検出したくないのですか?)。
  • 重要:静的ストレージ期間変数のデフォルト値への依存を実装しないでください。つまり、.dataまたはのデフォルトのコンテンツを信頼しないでください.bss。初期化の時点から変数が実際に使用される時点までの時間は任意である可能性があり、RAMが破損するのに十分な時間があった可能性があります。代わりに、そのような変数が初めて使用される直前に、そのような変数がすべて実行時にNVMから設定されるようにプログラムを記述します。

    実際には変数はファイルスコープで、またはとして宣言されている場合、このことを意味static、あなたは使用しないでください=初期化にを意味します(またはそうすることはできますが、どうしても値に依存できないため、無意味です)。使用する直前に、必ず実行時に設定してください。NVMからこのような変数を繰り返し更新できる場合は、更新してください。

    同様に、C ++では、静的ストレージ期間変数のコンストラクターに依存しないでください。コンストラクターにパブリックの「セットアップ」ルーチンを呼び出させます。これは、呼び出し元のアプリケーションから直接実行時に呼び出すこともできます。

    可能であれば、初期化.dataおよび.bss(およびC ++コンストラクターの呼び出し)を行う「コピーダウン」スタートアップコードを完全に削除し、それに依存するコードを記述した場合にリンカーエラーが発生するようにします。多くのコンパイラには、これをスキップするオプションがあります。これは通常、「最小/高速起動」などと呼ばれます。

    これは、外部ライブラリがそのような依存を含まないようにチェックする必要があることを意味します。

  • 重大なエラーが発生した場合に元に戻すプログラムの安全な状態を実装および定義します。

  • エラーレポート/エラーログシステムの実装は常に役立ちます。

ブール値の破損(例のリンクのように)に対処する1つの方法は、TRUEequalを0xffffffff次に使用POPCNTしてしきい値を指定することです。
wizzwizz4

@ wizzwizz4値0xffがプログラムされていないフラッシュセルのデフォルト値であることを考えると、悪い考えのように思えます。
ランディン

%01010101010101010101010101010101、XOR、次にPOPCNT?
wizzwizz4

1
@ wizzwizz4または、C標準で要求されている値0x1のみ。
ランディン

1
@ wizzwizz4上記の方法(ECC、CRCなど)の一部またはすべてを使用する理由。そうしないと、宇宙線が.textセクション内の1ビットを反転させ、オペコードなどを変更する可能性があります。
ランディン

34

Cを使用して、このような環境で堅牢に動作するプログラムを作成することは可能ですが、それはほとんどの形式のコンパイラー最適化が無効になっている場合に限られます。最適化コンパイラーは、一見冗長なコーディングパターンの多くを「より効率的な」ものに置き換えるように設計されており、他に何も保持できない可能性があることをx==42コンパイラーが知っているときにプログラマーがテストする理由は、プログラマーがx防止したいためです。x他の値を保持した状態での特定のコードの実行-その値を保持できる唯一の方法が、システムが何らかの電気的異常を受信した場合であってもです。

変数を宣言することvolatileはしばしば役立ちますが、万能薬ではないかもしれません。特に重要な点として、安全なコーディングでは、危険な操作にはハードウェアインターロックが必要であり、アクティブ化には複数のステップが必要であり、コードは次のパターンを使用して記述される必要があることに注意してください。

... code that checks system state
if (system_state_favors_activation)
{
  prepare_for_activation();
  ... code that checks system state again
  if (system_state_is_valid)
  {
    if (system_state_favors_activation)
      trigger_activation();
  }
  else
    perform_safety_shutdown_and_restart();
}
cancel_preparations();

コンパイラがコードを比較的文字通りに変換し、システム状態のすべてのチェックが prepare_for_activation()場合、システムは、プログラムカウンタとスタックを任意に破損させるものであっても、ほとんどすべての単一のグリッチイベントに対して堅牢である可能性があります。への呼び出しの直後にグリッチが発生した場合prepare_for_activation()、それはアクティブ化が適切であったことを意味します(prepare_for_activation()グリッチの前に呼び出される理由が他にないため )。グリッチが原因でコードがprepare_for_activation()不適切に到達しても、その後にグリッチイベントが発生しない場合trigger_activation()、検証チェックを通過するか、cancel_preparationsを最初に呼び出さないと、コードが後で到達することはできません(スタックグリッチが発生した場合、実行はスポットに進む可能性があります直前trigger_activation()prepare_for_activation()呼び出したコンテキストが戻った後、への呼び出しがの呼び出しのcancel_preparations()間に発生したため、後者の呼び出しは無害になります。prepare_for_activation()し、trigger_activation()

このようなコードは、従来のCでは安全ですが、最新のCコンパイラでは安全ではありません。そのようなコンパイラは、そのような環境では非常に危険です。積極的に積極的にコードを含めるように努めているため、明確に定義されたメカニズムを介して発生する可能性があり、その結果も明確に定義されている状況に関連します。障害を検出してクリーンアップすることを目的とするコードは、場合によっては事態を悪化させることがあります。試みられたリカバリーが未定義の動作を引き起こす場合があるとコンパイラーが判断した場合、そのようなケースでそのようなリカバリーを必要とする条件が起こり得ないと推測し、それによりそれらをチェックするコードを排除します。


6
現実的に言えば、提供されていない最新のコンパイラー-O0や同等のスイッチはいくつありますか?GCCは、ユーザーに許可を与えると多くの奇妙なことを行いますが、許可しないように依頼すると、通常はかなり文字どおりのこともできます。
Leushenko

24
申し訳ありませんが、このアイデアは根本的に危険です。最適化を無効にすると、プログラムが遅くなります。または、言い換えれば、より高速なCPUが必要です。偶然にも、トランジスタゲートの電荷が小さいため、CPUが高速になるほど高速になります。これはそれらをはるかに放射線の影響を受けやすくします。より良い戦略は、単一の光子が少しノックする可能性がはるかに低い遅い大きなチップを使用し、で速度を取り戻すこと-O2です。
MSalters

27
-O0悪い考えである二次的な理由は、それがはるかに役に立たない命令を発するからです。例:インライン化されていない呼び出しには、レジスタの保存、呼び出し、レジスタの復元の指示が含まれています。これらはすべて失敗する可能性があります。そこにない命令は失敗することはありません。
MSalters

15
もう1つの理由-O0は悪い考えです。レジスタではなくメモリに変数を格納する傾向があります。現在、メモリがSEUの影響を受けやすいかどうかは定かではありませんが、処理中のデータは保存されているデータよりも影響を受けやすくなっています。無駄なデータの移動は避けてください-O2
MSalters

9
@MSalters:重要なのは、データが中断の影響を受けないということではなく、システムが要件を満たす方法で中断を処理できることです。多くのコンパイラーでは、すべての最適化を無効にすると、レジスター間でのレジスタの移動を過度に実行するコードが生成されますが、これは悪いことですが、変数をメモリーに格納する方が、レジスターに保持するよりもリカバリーの観点から安全です。メモリに2つの変数があり、それらが何らかの条件に従うと想定されている場合(たとえばv1=v2+0xCAFEBABE、2つの変数に対するすべての更新が行われます...
supercat

28

これは非常に幅広いテーマです。基本的に、メモリ破損から実際に回復することはできませんが、少なくともすぐ失敗するように試みることができます。使用できるいくつかのテクニックを次に示します。

  • チェックサム定数データ。長期間一定した構成データ(構成したハードウェアレジスタを含む)がある場合は、初期化時にチェックサムを計算し、定期的に確認します。不一致が見つかった場合は、再初期化またはリセットする必要があります。

  • 冗長性のある変数を格納します。あなたは重要な変数を持っている場合はx、その値を書き込むx1x2およびx3としてそれを読みます(x1 == x2) ? x2 : x3

  • プログラムフロー監視を実装します。メインループから呼び出される重要な関数/ブランチで一意の値を持つグローバルフラグをXORします。100%に近いテストカバレッジで放射線のない環境でプログラムを実行すると、サイクルの最後にフラグの許容値のリストが表示されます。偏差がある場合はリセットします。

  • スタックポインタを監視します。メインループの開始時に、スタックポインターをその期待値と比較します。偏差でリセットします。


27

あなたを助けることができるのは番犬ですです。ウォッチドッグは、1980年代に産業用コンピューティングで広く使用されました。ハードウェア障害は、それよりもはるかに一般的でした-別の答えもその期間を指します。

ウォッチドッグは、ハードウェアとソフトウェアを組み合わせた機能です。ハードウェアは、数値(たとえば1023)からゼロまでカウントダウンする単純なカウンターです。TTLまたはその他のロジックを使用できます。

ソフトウェアは、1つのルーチンがすべての重要なシステムの正しい動作を監視するように設計されています。このルーチンが正しく完了すると、コンピュータは正常に動作していることがわかり、カウンタが1023に戻ります。

全体的な設計は、通常の状況下では、ソフトウェアがハードウェアカウンターがゼロになるのを防ぐようになっています。カウンターがゼロに達すると、カウンターのハードウェアがその唯一のタスクを実行し、システム全体をリセットします。カウンターの観点からは、ゼロは1024に等しく、カウンターは再びカウントダウンを続けます。

このウォッチドッグにより、接続されたコンピューターは、多くの場合に障害が発生したときに再起動されます。今日のコンピューターでこのような機能を実行できるハードウェアに精通していないことを認めざるを得ません。外部ハードウェアへのインターフェースは、以前よりもはるかに複雑になりました。

ウォッチドッグの固有の欠点は、システムに障害が発生してからウォッチドッグカウンターがゼロ+再起動時間に達するまでシステムを使用できないことです。その時間は、一般的に外部または人間の介入よりもはるかに短いですが、サポートされる機器は、その時間枠でコンピュータ制御なしで続行できる必要があります。


9
TTL標準ICを備えたバイナリカウンターウォッチドッグは、確かに1980年代のソリューションです。それをしないでください。今日、ウォッチドッグ回路が組み込まれていないMCUは市場に存在しません。確認する必要があるのは、組み込みのウ​​ォッチドッグに個別のクロックソースがあるかどうか(良い場合が多い)、またはシステムクロックからクロックを継承しているかどうか(悪い場合)だけです。
ランディン

1
または、FPGAにウォッチドッグを実装します:ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20130013486.pdf
nos

2
ちなみに、依然として組み込みプロセッサで広く使用されています。
グラハム

5
@ピーター・モーテンセンは、この質問に対するすべての回答で編集をやめてください。これはウィキペディアではなく、それらのリンクは役に立ちません(そして、誰もがとにかくウィキペディアを見つける方法を知っていると確信しています...)。トピックがわからないため、編集内容の多くは正しくありません。私はそれらに遭遇したときに、あなたの誤った編集をロールバックしています。あなたはこのスレッドを上手く回すのではなく、もっと悪い方向に向かっています。編集を停止します。
ランディン

Jack Ganssleがウォッチドッグに関する優れた記事を公開しています:ganssle.com/watchdogs.htm
Igor Skochinsky

23

この回答は、システムが正常に動作することに加えて、最小コストまたは高速のシステムに関心があることを前提としています。放射性のもので遊ぶほとんどの人々は正確さ/速度より安全/コストを重視します

何人かはあなたができるハードウェアの変更を提案しました(罰金-答えにはたくさんの良いものがたくさんあります、そして私はそれのすべてを繰り返すつもりはありません)、そして他の人は冗長性を提案しました(原理的には素晴らしい)が、私は思いませんその冗長性が実際にどのように機能するかを誰もが提案しました。どのようにフェイルオーバーしますか?何かが「うまくいかなかった」とき、どうやって知るのですか?多くのテクノロジーはすべてが機能することに基づいて機能するため、障害は対処が難しい問題です。ただし、スケール用に設計された一部の分散コンピューティングテクノロジーでは、障害が予想されます(結局、十分なスケールがあるため、単一ノードのMTBFでは、多数のノードのうち1つのノードの障害は避けられません)。これを環境に利用できます。

ここにいくつかのアイデアがあります:

  • ハードウェア全体が複製されるn時間(ここnで、2より大きい、できれば奇数)であること、および各ハードウェア要素が他のハードウェア要素と通信できることを確認してください。イーサネットはそのための明白な方法の1つですが、より優れた保護を提供する他の多くのはるかに単純なルート(CANなど)があります。一般的なコンポーネント(電源も含む)を最小限に抑えます。これは、たとえば複数の場所でADC入力をサンプリングすることを意味します。

  • アプリケーションの状態が1つの場所(有限状態マシンなど)にあることを確認します。これは完全にRAMベースにすることができますが、安定したストレージを排除するものではありません。したがって、いくつかの場所に保管されます。

  • 状態の変化に定足数プロトコルを採用します。たとえば、RAFTを参照してください。C ++で作業しているので、このためのよく知られたライブラリがあります。FSMへの変更は、大多数のノードが同意した場合にのみ行われます。自分でロールするのではなく、プロトコルスタックとクォーラムプロトコル用の既知の適切なライブラリを使用してください。そうしないと、クォーラムプロトコルがハングアップすると、冗長性に関するすべての優れた作業が無駄になります。

  • FSMのチェックサム(CRC / SHAなど)を確認し、CRC / SHAをFSM自体に保存します(メッセージを送信し、メッセージ自体をチェックサム計算するだけでなく)。これらのチェックサム、チェックサム着信メッセージに対してFSMを定期的にチェックするようにノードを取得し、チェックサムがクォーラムのチェックサムと一致することを確認します。

  • できるだけ多くの他の内部チェックをシステムに組み込んで、独自の障害の再起動を検出するノードを作成します(十分なノードがある場合、これは半分の作業を続行するよりも優れています)。再起動しない場合に備えて、再起動中にクォーラムから完全に削除されるようにします。再起動時に、ソフトウェアイメージ(およびそれらがロードするその他すべて)のチェックサムを取得し、クォーラムに再導入する前に完全なRAMテストを実行します。

  • ハードウェアを使用してサポートしますが、慎重に行ってください。たとえば、ECC RAMを取得し、定期的に読み書きしてECCエラーを修正できます(エラーが修正できない場合はパニックになります)。ただし、(メモリから)スタティックRAMは、最初のDRAMよりも電離放射線に対する耐性がはるかに高いため、代わりにスタティックDRAMを使用することをお勧めします。「やらないこと」の最初の点も見てください。

1日以内に特定のノードに障害が発生する可能性が1%あるとします。障害を完全に独立させることができるとします。5つのノードがある場合、1日以内に3つ失敗する必要があります。これは、.00001%の確率です。もっと、まあ、あなたはアイデアを得ます。

私がやらないこと:

  • 最初から問題がないことの価値を過小評価します。重量が問題にならない限り、デバイスの周囲にある大きな金属ブロックは、プログラマーのチームが思いつくよりもはるかに安価で信頼性の高いソリューションになります。EMIの入力の同上光学結合は問題などです。それでも、電離放射線に対して最高の定格のコンポーネントを供給するようにコンポーネントを調達する場合は、試みてください。

  • 独自のアルゴリズムを実行します。人々はこれを以前にやったことがあります。彼らの仕事を使用してください。フォールトトレランスと分散アルゴリズムは困難です。可能な場合は他の人の作品を使用してください。

  • 複雑なコンパイラ設定を使用して、より多くの障害を検出することを希望します。運が良ければ、さらに障害を検出する可能性があります。おそらく、特に自分でロールした場合は、テストされていないコンパイラー内のコードパスを使用します。

  • 環境でテストされていないテクニックを使用してください。高可用性ソフトウェアを作成するほとんどの人は、HAが正しく機能することを確認するために障害モードをシミュレートする必要があり、その結果、多くの障害モードを見逃します。あなたはオンデマンドで頻繁に失敗する「幸運な」立場にいます。したがって、各手法をテストし、そのアプリケーションが実際にMTBFを導入するための複雑さを超える量(MTBが複雑になるとバグが発生する)を改善することを確認します。特に、これを私の定足数アルゴリズムなどのアドバイスに適用します。


2
イーサネットは、ミッションクリティカルなアプリケーションで使用するのはおそらく良い考えではありません。I2Cも、PCBの外にありません。CANのような頑丈なものの方がはるかに適しています。
ランディン

1
@Lundinフェアポイント。ただし、光学的に接続されているもの(イーサネットを含む)は問題ありません。
16

1
物理メディアは、イーサネットが不適切である理由ではありませんが、確定的なリアルタイム動作の欠如です。今日では多少信頼性の高いイーサネットを提供する方法もあると思いますが、私は古い習慣からそれを商用/おもちゃの電子機器と一緒にグループ化するだけです。
ランディン

1
@Lundinは公平な点ですが、RAFTを実行するためにそれを使用することを提案しているように、アルゴリズムには(理論的には)非決定的なリアルタイム動作があります(たとえば、同時リーダー選出が結果としてCSMAに類似しています/ CD)。厳密なリアルタイムの動作が必要な場合、おそらく私の答えはイーサネットよりも多くの問題を抱えています(そして、私の返答の冒頭で、「正しい」は「速い」ことを犠牲にする可能性が高いと私が言ったことに注意してください)。私はあなたのポイントをCANに組み込んだ。
16

1
@Lundin:非同期の側面を含むシステムは、完全に非決定的であってはなりません。ソフトウェアプロトコルが適切な方法でセットアップされ、デバイスに一意のIDがあり、デバイス数に既知の制限がある場合(デバイスが多いほど、サイズが大きいほど、イーサネットの最悪の場合の動作は、ハードウェアの中断がない場合に制限されると思います)最悪の場合の再試行回数)。
スーパーキャット2017

23

ソフトウェアソリューションを具体的に要求し、C ++を使用しているので、演算子のオーバーロードを使用して独自の安全なデータ型を作成してみませんか?例えば:

代わりに使用するuint32_t(およびdoubleint64_tなど)、あなた自身の作るSAFE_uint32_tのuint32_tの倍数(3の最小値)が含まれています。実行するすべての操作(* +-/ << >> = ==!=など)をオーバーロードし、オーバーロードされた操作を各内部値に対して個別に実行するようにします。つまり、一度実行して結果をコピーしないでください。前と後の両方で、すべての内部値が一致することを確認します。値が一致しない場合、間違った値を最も一般的な値に更新できます。最も一般的な値がない場合は、エラーがあることを安全に通知できます。

このようにして、ALU、レジスタ、RAM、またはバスで破損が発生しても問題はありませんが、複数回試行してもエラーが発生する可能性が高くなります。ただし、これは置き換え可能な変数に対してのみ機能することに注意してください。たとえば、スタックポインターは依然として影響を受けます。

余談:古いARMチップでも同様の問題が発生しました。これは古いバージョンのGCCを使用したツールチェーンであり、使用した特定のチップとともに、特定のエッジケースでバグをトリガーし、関数に渡される値が(場合によっては)破損することが判明しました。放射能のせいにする前に、デバイスに問題がないことを確認してください。そうです、場合によっては、コンパイラのバグです=)


1
これらの提案のいくつかは、破損を検出するための同様の「マルチビット健全性チェック」の考え方に沿って何かを持っている私は本当に安全重視のカスタムデータ型の提案で最もしかしこのような
WearyWanderer

2
各冗長ノードが異なるチームによって設計および開発されたシステムが世界中にあり、それらが同じソリューションに誤って解決しないようにアービターがいます。そうすれば、同じバグのためにそれらすべてがダウンすることはなく、同様のトランジェントは同様の障害モードを明示しません。
jwdonahue 2018年

16

免責事項:私は放射能の専門家ではなく、この種のアプリケーションのために働いていません。しかし、重要なデータをある程度アーカイブするために、ソフトエラーと冗長性に取り組みましたが、これはある程度関連しています(同じ問題、異なる目標)。

私の意見では、放射能の主な問題は、放射能がビットを切り替える可能性があるため、放射能がデジタルメモリを改ざんする可能性があることです。これらのエラーは通常、ソフトエラー、ビット腐敗などと呼ばれます。

問題は、メモリが信頼できない場合にどのようにして信頼性の高い計算を行うかということです。

ソフトエラーの発生率を大幅に削減するには(ほとんどがソフトウェアベースのソリューションであるため、計算のオーバーヘッドが犠牲になります)、次のいずれかを実行できます。

  • 古き良き冗長性スキーム、より具体的にはより効率的なエラー訂正コードに依存します(同じ目的ですが、冗長性を減らしてより多くのビットを回復できるようにアルゴリズムを巧妙にしています)。これは、(誤って)チェックサムと呼ばれることもあります。この種のソリューションでは、いつでもプログラムの完全な状態をマスター変数/クラス(または構造体?)に格納し、ECCを計算して、何かを行う前に、ECCが正しいことを確認する必要があります。フィールドを修復しないでください。ただし、このソリューションは、ソフトウェアが動作することを保証するものではありません(単に動作する場合は正しく動作し、動作しない場合は動作を停止します。ECCが問題を通知できるためです。この場合、ソフトウェアを停止して、偽の結果を取得しないでください)。

  • またはあなたが使うことができます 回復力のあるアルゴリズムデータ構造をは、ソフトエラーが発生した場合でもプログラムが正しい結果を提供することを保証します。これらのアルゴリズムは、一般的なアルゴリズム構造とECCスキームがネイティブに混在しているものと見なすことができますが、これは、復元力スキームが構造に厳密にバインドされているため、追加のプロシージャをエンコードする必要がないため、それよりもはるかに回復力があります。 ECCをチェックします。通常は、はるかに高速です。これらの構造は、ソフトエラーの理論上の限界まで、プログラムがあらゆる条件下で機能することを保証する方法を提供します。これらの回復力のある構造を冗長性/ ECCスキームと組み合わせてセキュリティを強化することもできます(または、最も重要なデータ構造を回復力のあるものとしてエンコードし、残りの部分はメインデータ構造から再計算できる使い捨てデータをエンコードします。

復元力のあるデータ構造(アルゴリズムおよび冗長エンジニアリングにおける最近の、しかし刺激的な新しい分野)に関心がある場合は、次のドキュメントを読むことをお勧めします。

  • 弾力性のあるアルゴリズムのデータ構造の紹介in Giuseppe F.Italiano、Universita di Roma "Tor Vergata"

  • Christiano、P.、Demaine、ED、およびKishore、S。(2011)。付加的なオーバーヘッドがあるロスレスのフォールトトレラントデータ構造。アルゴリズムとデータ構造(pp。243-254)。スプリンガーベルリンハイデルベルク。

  • Ferraro-Petrillo、U.、Grandoni、F。、およびItaliano、GF(2013)。メモリ障害に強いデータ構造:辞書の実験的研究。Journal of Experimental Algorithmics(JEA)、18、1-6。

  • イタリア語、GF(2010)。弾力性のあるアルゴリズムとデータ構造。アルゴリズムと複雑さ(p。13-24)。スプリンガーベルリンハイデルベルク。

復元力のあるデータ構造の分野について詳しく知りたい場合は、ジュゼッペF.イタリアーノの作品をチェックアウトして(参考文献を参照してください)、障害のあるRAMモデル(Finocchi et al。2005で導入された; Finocchi。 and Italiano 2008)。

/編集:主にRAMメモリとデータストレージを対象としたソフトエラーの防止/回復について説明しましたが、計算(CPU)エラーについては触れませんでした。他の回答は、データベースのようにアトミックトランザクションを使用することをすでに指摘しているため、別のより簡単なスキームを提案します。冗長性と多数決。です。

つまり、必要な計算ごとに同じ計算x回実行し、その結果をx個の異なる変数に格納します(x> = 3)。次に、x変数を比較できます

  • それらがすべて一致すれば、計算エラーはまったくありません。
  • 同意しない場合は、過半数の投票を使用して正しい値を取得できます。これは、計算が部分的に破損していることを意味するため、システム/プログラムの状態スキャンをトリガーして、残りが問題ないことを確認することもできます。
  • 多数決で勝者を決定できない場合(すべてのx値が異なる)、フェイルセーフ手順(再起動、ユーザーへのアラートの生成など)をトリガーするのに最適なシグナルです。

この冗長性スキームは、ECC(実際にはO(1))と比較して非常に高速であり、フェイルセーフが必要場合に明確な信号を提供します。過半数の投票は、(ほとんど)破損した出力生成せず、小さな計算エラーから回復することも保証されています。これは、x計算で同じ出力が得られる確率が非常に小さいためです(可能な出力が大量にあるため、ほとんど不可能です)。ランダムに3回同じものを取得します。x> 3の場合、確率はさらに低くなります。

したがって、過半数の投票により、破損した出力から安全であり、冗長性x == 3を使用すると、1つのエラーを回復できます(x == 4を使用すると、2つのエラーを回復できます)。正確な方程式はnb_error_recoverable == (x-2)、xが数値過半数の投票を使用して回復するには、少なくとも2つの同意する計算が必要なため、計算の繰り返し。

欠点は、1回ではなくx回計算する必要があるため、追加の計算コストがかかりますが、線形の複雑さであるため、漸近的に、得られる利点をあまり失うことはありません。多数決を行うための迅速な方法は、配列のモードを計算することですが、中央値フィルターを使用することもできます。

また、計算が正しく行われていることを確認したい場合は、独自のハードウェアを作成できれば、x CPUでデバイスを構築し、システムを配線して、計算がx CPU間で自動的に複製され、多数決が行われます。最後に機械的に(たとえば、AND / ORゲートを使用して)。これは、飛行機やミッションクリティカルなデバイスに実装されることがよくあります(トリプルモジュールの冗長性を参照)。このようにすると、追加の計算が並行して行われるため、計算のオーバーヘッドがなくなり、ソフトエラーからの保護の別のレイヤーが得られます(計算の重複と多数決はハードウェアによって直接管理されるため、ソフトウェア-プログラムは単にメモリに格納されたビットなので、破損しやすくなります...)。


9

誰も言及していないようです。あなたはGCCで開発していて、ARMにクロスコンパイルしていると言います。空きRAM、整数サイズ、ポインターサイズ、特定の操作を実行するのにかかる時間、システムが継続的に実行される時間、またはそのようなさまざまなことを想定したコードがないことをどのようにして知っていますか?これは非常に一般的な問題です。

答えは通常自動化された単体テストです。開発システムでコードを実行するテストハーネスを記述し、ターゲットシステムで同じテストハーネスを実行します。違いを探してください!

また、組み込みデバイスのエラッタも確認してください。「クラッシュするので、これを行わないでください。そのコンパイラー・オプションを有効にすると、コンパイラーはそれを回避します」という何かがあるかもしれません。

つまり、クラッシュの原因として最も可能性が高いのは、コードのバグです。これが当てはまらないことを確認するまでは、より難解な障害モードについて(まだ)心配する必要はありません。


1
確かに、質問のテストのどこにも、著者は、アプリケーションが放射性環境の外で正常に動作することがわかったと述べています。
Marc.2377

9

放射線環境の外部にマスターを持つ3台以上のスレーブマシンが必要です。すべてのI / Oは、投票や再試行メカニズムを含むマスターを通過します。スレーブはそれぞれハードウェアウォッチドッグを備えている必要があり、それらをバンプする呼び出しはCRCなどで囲まれ、不本意なバンプの可能性を減らす必要があります。バンピングはマスターによって制御される必要があるため、マスターとの接続が失われると、数秒以内に再起動します。

このソリューションの利点の1つは、マスターとスレーブで同じAPIを使用できるため、冗長性が透過的な機能になることです。

編集:コメントから、「CRCのアイデア」を明確にする必要があると感じています。マスターからのランダムデータのCRCまたはダイジェストチェックでバンプを囲む場合、スレーブが自身のウォッチドッグをバンプする可能性はゼロに近くなります。このランダムデータは、監視対象のスレーブが他のスレーブと整列している場合にのみマスターから送信されます。ランダムデータとCRC /ダイジェストは、各バンプの直後にクリアされます。マスタースレーブのバンプ周波数は、ウォッチドッグタイムアウトの2倍以上である必要があります。マスターから送信されるデータは毎回一意に生成されます。


7
私は、放射環境の外にマスターを置くことができ、放射環境の外にスレーブを置くことができなかった、放射環境内のスレーブと確実に通信できるシナリオを理解しようとしています。
2016

1
@fostandy:スレーブは、コントローラを必要とする機器を使用して測定または制御しています。ガイガーカウンターと言います。マスターは、スレーブの冗長性により、信頼できる通信を必要としません。
JonasByström16年

4
マスターを導入しても、自動的にセキュリティが強化されるわけではありません。メモリの破損が原因でスレーブxが狂ってしまい、「マスターはここにいる、マスターは満足している」と繰り返し言い続けている場合、マスターによるCRCまたはバーク注文の量はそれを保存しません。あなたはマスターにそのスレーブの力を切る可能性を与えなければならないでしょう。また、一般的な原因のエラーがある場合、スレーブを追加しても安全性は向上しません。また、ソフトウェアのバグの量と壊れる可能性のあるものの量は、複雑さとともに増加することにも留意してください。
ランディン

5
そうは言っても、当然のことながら、放射性環境内の電子機器を可能な限りシンプルに保ちながら、プログラムの多くをより公開されていない場所に「外部委託」するのは良いことです。
ランディン

7

アプリケーションの多くのインスタンスを実行するのはどうでしょう。クラッシュの原因がランダムなメモリビットの変更である場合、アプリインスタンスの一部が問題を解決し、正確な結果を生成する可能性があります。(統計的背景を持つ人にとって)希望するだけの小さな全体的なエラーを達成するためにビットフロップ確率を指定する必要があるインスタンスの数を計算することはおそらく非常に簡単です。


2
確かに、組み込みシステムは、いくつかのインスタンスを起動してハードウェア要件を引き上げ、少なくとも1つのインスタンスが大丈夫であるという盲目的な運命を期待するよりも、堅牢なアプリケーションの1つのインスタンスで安全上重要なキャッチを優先します。私はそのアイデアを理解し、それは有効ですが、力ずくで頼らない提案にもっと傾けます
WearyWanderer

7

あなたが尋ねることは非常に複雑なトピックです-簡単に答えられません。他の答えも問題ありませんが、それらはあなたがする必要があるすべてのことのほんの一部をカバーしました。

コメントに見られるようにで、ハードウェアの問題を100%修正することは不可能ですが、高い確率で、さまざまな手法を使用してそれらを削減または捕捉することが可能です。

私があなたなら、最高の安全度水準レベル(SIL-4)のソフトウェアを作成します。IEC 61513ドキュメント(原子力業界向け)を入手し、それに従ってください。


11
または、技術要件を読み、意味のあるものを実装してください。SIL標準の大部分はナンセンスであり、独断的にそれらに準拠すると、危険で危険な製品になってしまいます。今日のSIL認定は、主に大量のドキュメントを作成し、テストハウスに賄賂を渡すことに関するものです。SILレベルは、システムの実際の安全性については何も言いません。代わりに、実際の技術的な安全対策に集中する必要があります。SILドキュメントには非常に優れたものがいくつかあり、完全にナンセンスなものもいくつかあります。
ランディン

7

誰かが遅いチップを使用して、イオンがビットを簡単に反転しないようにすることについて言及しました 同様の方法で、実際には複数のビットを使用して単一のビットを格納する特殊なCPU / RAMを使用する可能性があります。したがって、すべてのビットが反転する可能性は非常に低いため、ハードウェアのフォールトトレランスを提供します。したがって、1 = 1111ですが、実際に反転するには4回ヒットする必要があります。(4は、2ビットを反転させるとすでにあいまいになるため、不適切な数値になる可能性があります)。したがって、8を使用すると、RAMが8分の1になり、アクセス時間が遅くなりますが、データ表現の信頼性は大幅に向上します。おそらく、専用のコンパイラ(すべてにx容量を割り当てる)または言語の実装(この方法でデータ構造を割り当てるデータ構造のラッパーを作成)を使用して、ソフトウェアレベルでこれを行うことができます。


7

おそらく、ハードウェアが「この環境向けに設計されている」ことを意味するかどうかを知ることは役立つでしょう。SEUエラーの存在をどのように修正および/または示しますか?

ある宇宙探査関連プロジェクトでは、SEUエラーで例外/割り込みを発生させるカスタムMCUがありましたが、SEU例外を引き起こした1つのinsnの後にいくつかのサイクルが渡される/命令が実行される場合があります。

特に脆弱なのはデータキャッシュでした。そのため、ハンドラーが問題のキャッシュラインを無効にし、プログラムを再起動します。それだけですが、例外の不明確な性質のため、insnを発生させる例外が先頭に立つ一連のinsnは、再起動できない場合があります。

危険な(再起動できない)シーケンスを特定し(たとえば、に変更され、データに依存しないlw $3, 0x0($2)insnが続く)、GCCに変更を加えたため、そのようなシーケンスは発生しません(たとえば、最後の手段として、による2つの宿題$2$3nop)。

考慮すべきことだけ...


7

ハードウェアに障害が発生した場合、機械的なストレージを使用して回復できます。コードベースが小さく、物理的なスペースがある場合は、Mechanicalデータストアを使用できます。

ここに画像の説明を入力してください

放射線の影響を受けない素材の表面があります。複数のギアがあります。機械式リーダーはすべてのギアで動作し、柔軟に上下に移動できます。Downは0、upは1を意味します。0と1からコードベースを生成できます。


2
おそらく、CD-ROMなどの光学媒体はこの定義を満たすでしょう。大容量の追加ボーナスがあります。
Wossname

2
はい、似ていますが、CD-ROMの使用は少なくなりますが、これは完全に機械的なシステムになります。
Hitul

7
空間でパンチカードリーダーを使わないのには理由があるのか​​しら。
Soren、2016年

3
@Soren速度と物理的なスペースが理由になり得ます。
Hitul

5

循環スケジューラを使用します。これにより、定期的なメンテナンス時間を追加して、重要なデータの正確性をチェックできます。最も頻繁に発生する問題は、スタックの破損です。ソフトウェアが循環的である場合、サイクル間でスタックを再初期化できます。スタックを割り込み呼び出しに再利用せず、重要な割り込み呼び出しごとに個別のスタックをセットアップします。

ウォッチドッグの概念と同様に、デッドラインタイマーがあります。関数を呼び出す前にハードウェアタイマーを開始します。デッドラインタイマーが中断する前に関数が返らない場合は、スタックをリロードして再試行してください。3/5を試しても失敗する場合は、ROMからリロードする必要があります。

ソフトウェアをパーツに分割し、これらのパーツを分離して、個別のメモリ領域と実行時間を使用します(特に制御環境で)。例:信号取得、重要なデータ、メインアルゴリズム、結果の実装/送信。これは、ある部分での障害が、プログラムの残りの部分での障害を引き起こさないことを意味します。したがって、信号取得を修復している間、残りのタスクは古いデータで続行されます。

すべてにCRCが必要です。RAMを使い果たした場合でも、.textにはCRCが必要です。循環スケジューラを使用している場合は、CRCを定期的にチェックしてください。一部のコンパイラ(GCCではない)は各セクションのCRCを生成でき、一部のプロセッサはCRC計算を実行するための専用ハードウェアを備えていますが、それは質問の範囲から外れると思います。CRCをチェックすると、メモリのECCコントローラーがシングルビットエラーを問題になる前に修復するように求められます。


4

まず、障害を中心にアプリケーションを設計します。通常のフロー操作の一部として、リセットが予期されることを確認します(アプリケーションと、ソフトまたはハードの障害の種類によって異なります)。これを完璧にすることは困難です。ある程度のトランザクション性を必要とする重要な操作は、アセンブリレベルでチェックおよび調整する必要がある場合があるため、重要なポイントでの中断によって一貫性のない外部コマンドが発生することはありません。 回復不可能なメモリの破損や制御フローの逸脱が検出されるとすぐに失敗します。可能であれば、失敗をログに記録します。

次に、可能であれば、破損を修正して続行します。これは、定数テーブル(および可能であればプログラムコード)のチェックサムと修正を頻繁に行うことを意味します。おそらく、各主要操作の前または時限割り込みで、自動修正する構造に変数を格納します(これも、各主要操作の前または時限割り込みで3から過半数の投票を取り、単一の偏差の場合は修正します)。可能であれば、修正をログに記録します。

第三に、テストの失敗。疑似ランダムにメモリ内のビットを反転させる再現可能なテスト環境をセットアップします。これにより、破損の状況を再現し、その周囲のアプリケーションの設計に役立ちます。


3

supercatのコメント、最近のコンパイラーの傾向などを考えると、古代に戻って、コード全体をアセンブリーおよび静的メモリー割り当てのどこにでも書きたくなります。この種の完全な信頼性のために、私は組み立てがコストの大きなパーセンテージの差を負わなくなったと思います。


私は(他の質問に対する私の答えからわかるように)アセンブリ言語の大ファンですが、これは良い答えだとは思いません。ほとんどのCコードのコンパイラーに何を期待するか(レジスター対メモリーに存在する値の観点から)を知ることはかなり可能であり、期待どおりであることを常に確認できます。手書き ASMでのプロジェクトは、非常に快適な書き込みARM asmのある開発者を持っている場合でも、余分な作業のちょうどトンです。同じ結果を3回計算するようなことをしたいのであれば、asmでいくつかの関数を書くのは理にかなっています。(コンパイラはそれをCSEで削除します)
Peter Cordes

さもなければ、それとバランスを取る必要があるより高いリスクは、コンパイラーのアップグレードであり、予期しない変更を残す可能性があります。
ジョシュア

1

ここに大量の返信がありますが、これについての私の考えを要約しようと思います。

何かがクラッシュしたり、正しく機能しない場合は、自分のミスが原因である可能性があります。問題を見つけたときに簡単に修正できるはずです。しかし、ハードウェア障害の可能性もあります-全体的に修正することは不可能ではないにしても困難です。

最初に、ログ(スタック、レジスター、関数呼び出し)を使用して問題のある状況をキャッチすることをお勧めします。

このようなエラー状態からの回復は、再起動(ソフトウェアがまだアクティブで起動している場合)またはハードウェアリセット(ハードウェアウォッチドッグなど)のいずれかです。最初から開始する方が簡単です。

問題がハードウェアに関連している場合-ロギングは、どの関数呼び出しの問題が発生しているかを特定するのに役立ち、何が機能しておらず、どこにあるのかを内部的に知ることができます。

また、コードが比較的複雑な場合-「分割統治」することには意味があります。つまり、問題があると思われる一部の関数呼び出しを削除または無効にします-通常、コードの半分を無効にして、もう半分を有効にします-「機能する」/ 「動作しない」という決定の後で、コードの別の半分に集中できます。(どこに問題がありますか)

しばらくして問題が発生した場合-スタックオーバーフローが疑われる可能性があります-スタックポイントレジスタが常に増加している場合は、監視することをお勧めします。

そして、「hello world」の種類のアプリケーションまでコードを完全に最小化することができ、それでもランダムに失敗する場合は、ハードウェアの問題が予想され、「ハードウェアのアップグレード」が必要です。つまり、そのようなcpu / ram / ...を発明する必要があります。 -放射をよりよく許容するハードウェアの組み合わせ。

最も重要なことは、おそらくマシンが完全に停止/リセット/機能しない場合にログをどのように戻すかです-おそらく最初のbootstapがすべきことは-問題のある状況が発見された場合の帰宅です。

ご使用の環境で信号を送信して応答を受信することも可能である場合-ある種のオンラインリモートデバッグ環境を構築してみることができますが、少なくとも通信メディアが機能し、プロセッサ/ RAMが機能している必要があります。リモートデバッグとは、GDB / gdbスタブのようなアプローチ、またはアプリケーションから取得する必要があるものの独自の実装(ログファイルのダウンロード、コールスタックのダウンロード、RAMのダウンロード、再起動など)を意味します


申し訳ありませんが、問題は、ハードウェア障害が発生する放射性環境についてです。あなたの答えは、一般的なソフトウェアの最適化とバグを見つける方法についてです。しかし、このような状況では、障害がバグによって生成されていません
ジェブ

はい、地球の重力、コンパイラの最適化、サードパーティのライブラリ、放射性環境なども非難できます。しかし、それはあなた自身のバグではないのですか?:-)証明されない限り-私はそうは思わない。ファームウェアの更新と電源オフの状況のテストを一度に実行しました。自分のバグをすべて修正した後でないと、ソフトウェアはすべての電源オフの状況に耐えました。(夜間の電源オフは4000以上)しかし、場合によってはバグがあったとは信じがたいです。特に、メモリの破損について話しているときは。
TarmoPikaro 2016年

0

私は本当にたくさんの素晴らしい答えを読みました!

これが私の2セントです。メモリをチェックしたり、レジスタの比較を頻繁に実行するソフトウェアを作成して、メモリ/レジスタの異常の統計モデルを構築します。さらに、問題を実験できる仮想マシンのスタイルでエミュレータを作成します。ジャンクションサイズ、クロック周波数、ベンダー、ケーシングなどを変更すると、異なる動作が観察されると思います。

私たちのデスクトップPCのメモリでさえも一定の割合の障害がありますが、それでも日常業務に支障はありません。

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