5

私はリアルタイム システムを開発しており、クラスの設計について議論しています。
具体的には、「重い」クラスを 2 フェーズ構成でビルドするかどうかを判断できません。

一方では、「重い」クラスのコンストラクターを呼び出すと、実行時の大きなボトルネックになる可能性があり、ユーザーが使用しない可能性のある機能のクラスを作成してメモリを割り当てる必要がなくなります。

一方、2 段階の構築では、アビリティにアクセスしようとしたが、初期化されていないためにアクセスできず、使用する前に突然完全に構築する必要がある場合を考えると、実行中に驚きが生じる可能性があります。

私の傾向は、2 段階の建設方法を採用することです。私が聞きたいのは、リアルタイムシステムでの 2 フェーズ構成の長所と短所です。そして、これに対するより良いアプローチがあれば。

これは重いクラスのコードです (私のクラスは確かにそのようには見えませんが、私の考えを示しています):

 class VeryHeavy {

 private:

    HeavyClass1* p1;
    HeavyClass2* p2;
    HeavyClass3* p3;
    HeavyClass4* p4;
    HeavyClass5* p5;

    int* hugeArray [100000];

    //...//

};
4

3 に答える 3

21

ここに画像の説明を入力

これは、アポロ司令船と月着陸船の両方で使用されているAGC、アポロ ガイダンス コンピューターです。アポロ 11 号の着陸をほぼ失敗に終わったことで有名です。月面への降下の最中、このコンピュータはリアルタイム エラーでクラッシュしました。数回。システム エラー 1201 (エグゼクティブ オーバーフロー - 空いている領域がない) およびシステム エラー 1202 (エグゼクティブ オーバーフロー - コア セットがない) を生成します。Armstrong と Aldrin は数字しか見ていませんでした。写真の右側にある UI デバイスは原始的すぎて文字列を表示できませんでした。数値が何を意味するかを知っていたのはガイダンス コントローラーのスティーブ ベイルズでした (彼らはトレーニング中にエラーを見たことがありませんでした)、システムがそれから回復できることを知っていました。とにかく GO を与えることによって着陸を救った、彼はそのために大統領自由勲章を取得しました。

これはおそらくあなたの質問が尋ねていることですが、あなたがロケットを着陸させようとしていないことはかなり確信で​​きます. 「リアルタイム」という用語は、以前はソフトウェア エンジニアリングでかなり明確に定義されていましたが、金融業界によって混乱してしまいました。アポロ 11 号では、外部イベントに対する最大応答時間の上限が非常に厳しいシステムを意味していました。ロケットにはそのようなシステムが必要です。ノズルを調整するときに遅すぎることはありません一度遅れると、10 億ドルの火球が発生します。金融業界はそれをハイジャックして、恣意的に高速なシステムを意味し、遅れてもマシンが蒸発することはありませんが、取引損失の可能性が高くなります. 彼らはおそらくそれも災害だと考えています:)

使用するメモリ アロケータは非常に重要であり、質問では定義されていません。勝手に、あなたのプログラムがデマンド ページ仮想メモリ オペレーティング システムで実行されていると仮定します。リアルタイム システムにとって理想的な環境とは言えませんが、十分に一般的な、真のリアルタイム オペレーティング システムはうまくいきませんでした。

2 フェーズの構築は、初期化の失敗に対処するために使用される手法です。コンストラクターでスローされた例外は処理が難しく、デストラクタが実行されないため、コンストラクターを十分にスマートにせずにコンストラクターで割り当てると、リソース リークが発生する可能性があります。事故に対処する。別の方法は、必要に応じて遅延割り当てを行い、メンバー関数内で後で行うことです。

したがって、あなたが心配しているのは、遅延割り当てがシステムの応答性を妨げることです。システム エラー 1201 の生成。

これは、実際には、Linux や Windows などのデマンド ページ仮想メモリ オペレーティング システムでは主要な懸念事項ではありません。これらのオペレーティング システムのメモリ アロケータは高速で、仮想メモリのみを割り当てます。何の費用もかからない、それは仮想です。実際にコストがかかるのは、割り当てられたメモリを実際に使い始めるときです。デマンドページの「デマンド」が登場する場所。配列要素をアドレス指定するとページ フォールトが発生し、オペレーティング システムはアドレス指定された仮想メモリ ページを RAM にマップする必要があります。このようなページ フォールトは、「ソフト」ページ フォールトと呼ばれる比較的低コストで発生します。これは、マシンに負荷がかかっておらず、RAM を取得するために別のプロセスで使用されているページのマップを解除する必要がある場合です。OS はページを取得してマップするだけでよいと考えているでしょう。

したがって、実際には、配列を割り当てるときに配列全体を初期化しようとしないで正しく行うと、プログラムは何万もの小さな針刺しのオーバーヘッドを受けることになります。リアルタイムの応答保証を危険にさらさないほど十分に小さい各 1 つ。これは、メモリの割り当てが早いか遅いかに関係なく発生するため、2 フェーズ構成を使用するかどうかは問題ではありません。

これが起こらないことを保証したい場合、または配列全体を初期化するときに発生する一連のページ フォールトに耐えられるようにしたい場合は、非常に異なるアプローチが必要になります。ページをロックする必要があります。オペレーティング システムがページのマップを解除できないように、RAM を割り当てます。これには常に OS 設定をいじる必要があり、通常、プロセスが大量のメモリをページロックすることはできません。2 段階の建設は、もちろんドアの外にもあります。

プログラムが割り当ての失敗を処理する方法を知っていることは非常にまれであることを覚えておいてください。それらは非同期例外のように動作し、プログラムのほぼすべての部分でいつでも発生する準備ができています。リアルタイムの要件との調整は特に難しく、メモリ不足のためにリアルタイム イベントに応答しないシステムは、もちろん、遅延したシステムに勝るものはありません。それはまだ火の玉です;)それ自体で、2フェーズの構築を気にしない十分な理由になるはずです。リアルタイム応答を約束する前に、プログラムの初期化時にメモリを割り当てるだけです。プログラムのコーディングが非常に簡単になり、失敗する可能性がはるかに低くなります

リアルタイムの特性で実行されるソフトウェアの非常に厳しい要件は、オペレーティング システムのリソースを取得するために他のプロセスと競合する必要がないことです。マシン全体を 1 つのプロセス専用にすることが期待されます。AGC のように、36864 ワードのロープ メモリと 2048 ワードの RAM に制限されることはありません。最近のハードウェアは安価で豊富にあり、そのような保証を提供できます。

于 2013-07-27T22:47:55.487 に答える