8

実行中のプログラムの状態をディスクに保存し、それを元に戻す基本原則を詳しく調べています。私たちが持っている現在の設計では、各オブジェクト(関数ポインタリストを備えたCレベルのものであり、一種の低レベルの自家製オブジェクト指向であり、このようにするのには非常に正当な理由があります)明示的な状態を書き込み可能で復元可能な形式にエクスポートするために呼び出されます。これを機能させるための重要な特性は、オブジェクトに関連するすべての状態が実際にオブジェクト データ構造にカプセル化されていることです。

一部のオブジェクトにアタッチされたユーザーレベルのスレッドがあるアクティブなオブジェクトを操作する他のソリューションがあります。したがって、プログラム カウンター、レジスタの内容、およびスタックの内容は、突然プログラム状態の一部になります。私の知る限り、そのようなものを任意の時点でディスクにシリアライズする良い方法はありません。スレッドは、プログラムカウンターなどによって何も表されない特別な状態に自分自身をパークする必要があるため、基本的に実行状態マシンの状態を明示的なオブジェクト状態に「保存」する必要があります。

私はさまざまなシリアライゼーション ライブラリを見てきましたが、これは普遍的なプロパティであると言えます。

中心的な質問は次のとおりです。それとも、実際にはそうではないのでしょうか。スレッドが実行されているコードの場所に関して、スレッドの状態を含めることができる保存/復元ソリューションはありますか?

システム状態全体を仮想マシンに保存することはカウントされないことに注意してください。これは実際には状態をシリアル化するのではなく、マシンをフリーズして移動するだけです。これは明らかな解決策ですが、ほとんどの場合、少し重いです。

いくつかの質問により、私たちが物事をどのように行うかという考えを十分に説明できていないことが明らかになりました。私たちはシミュレーターシステムに取り組んでおり、その中で実行されるコードに対して非常に厳しいルールを書くことが許可されています。特に、オブジェクトの構築とオブジェクトの状態を完全に区別します。インターフェイス関数ポインターは、システムをセットアップするたびに再作成され、状態の一部ではありません。状態は、内部ランタイム表現とストレージ表現の間で変換する定義済みの get/set 関数をそれぞれ持つ特定の指定された「属性」のみで構成されます。オブジェクト間のポインターの場合、それらはすべて名前に変換されます。したがって、私たちの設計では、オブジェクトはストレージ内で次のようになる可能性があります。

Object foo {
  value1: 0xff00ff00;
  value2: 0x00ffeedd;
  next_guy_in_chain: bar;
}

Object bar {
  next_guy_in_chain: null;
}

リンクされたリストは、シミュレーション構造に実際に存在することはありません。各オブジェクトは、ある種のハードウェアのユニットを表します。

問題は、一部の人々がこれを行いたいが、動作をコード化する方法としてスレッドを持っていることです。ここでの「動作」は、実際にはシミュレーション ユニットの状態の変化です。基本的に、私たちが持っている設計では、そのような変更はすべて、呼び出され、作業を行い、戻るアトミックな完全操作で行う必要があると述べています。すべての状態はオブジェクトに格納されます。リアクティブ モデルがあるか、「完了まで実行」または「イベント ドリブン」と呼ぶことができます。

これについての別の考え方は、オブジェクトにアクティブなスレッドを持たせることです。これは、古典的な Unix スレッドと同じように永久ループに留まり、決して終了しません。これは、ディスクに適切に保存できるかどうかを確認しようとしているケースですが、その下に VM を挿入しないと実現できないようです。

更新、2009 年 10 月:これに関連する論文が 2009 年の FDL カンファレンスで公開されました。チェックポイントと SystemC に関するこの論文を参照してください。

4

7 に答える 7

2

同期の問題が発生するため、プログラムの「一部のスレッド」のみをシリアル化することはできないと思います(問題の一部については、http://java.sun.com/j2se/1.3/docs/guideで説明しています)。 /misc/threadPrimitiveDeprecation.html)。したがって、プログラム全体を永続化することが、一貫した状態を取得するための唯一の実行可能な方法です。

あなたが調べるかもしれないのは直交永続性です。いくつかの典型的な実装があります:

http://research.sun.com/forest/COM.Sun.Labs.Forest.doc.external_www.PJava.main.html

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.7429

しかし、それらのどれももう維持されていないか、多くの魅力を獲得していません(afaik)。結局のところ、チェックポイントは最善の解決策ではないと思います。私自身のプロジェクトhttp://www.siebengeisslein.orgでは、軽量トランザクションを使用してイベントをディスパッチするアプローチを試みているため、スレッドの状態を維持する必要はありません(トランザクションの終了時に、スレッドのコールスタックが再び空になるため) 、およびトランザクションの途中で操作が停止した場合、すべてがロールバックされるため、スレッドのコールスタックも重要です)。おそらく、どのOODBMSでも同様のことを実装できます。

物事を見る別の方法は継続です(http://en.wikipedia.org/wiki/Continuation、http://jauvm.blogspot.com/ 。これらは、定義されたコードの場所で実行を一時停止する方法です(ただし、必ずしもスレッドの状態を保持しているわけではありません)。

これがあなたにいくつかの出発点を与えることを願っています(しかし、このafaikに対するすぐに使える解決策はありません)。

編集:説明を読んだ後:あなたは間違いなくOODBMSを調べる必要があります。各イベントを独自のトランザクションでディスパッチし、スレッドを気にしません。

于 2008-10-08T18:48:22.680 に答える
1

プログラムの状態をシリアライズしようとするよりも優れたアプローチは、データ チェックポイントを使用してCrash Only Softwareを実装することです。データ チェックポイントの実行方法は、実装と問題のドメインによって異なります。

于 2008-10-08T18:58:11.053 に答える
1

仮想マシンの状態を保存し、まったく同じ方法で復元できることは、まさにあなたが望んでいることのように思えます。

前回の実行で使用していたのと同じデータで実行中のプログラムを開始できることだけが必要な場合は、永続データを保存して復元するだけで済みます。各スレッドの正確な状態はそれほど重要ではありません。とにかく非常に速く変化します-そして、物事の実際のアドレスは次回は異なります. とにかく、データベースを使用すると、この機能が得られるはずです。

于 2008-10-08T18:29:33.077 に答える
0

プログラムがディスクに接続しなければならない状態をシリアル化しようとしないでください。プログラムは、オペレーティングシステムによって許可されていない限り、その状態を完全に制御することはできません。その場合、プログラムはオペレーティングシステムの一部です。

プログラムにとって、仮想メモリに対するオペレーティングシステムの選択は次のとおりであるため、ある仮想メモリの場所へのポインタが同じ仮想メモリの場所を再び指すことを保証することはできません(heap-begin / end、stack-beginなどのプロパティを除く)。不確定。sbrkまたはmallocなどの上位レベルのインターフェイスを介してOSに要求するページは、どこからでも開始されます。

より良い:

  • コードをきれいにし、デザインを検査します。どのような状態のプロパティがその一部ですか?
  • このような低水準言語は使用しないでください。実行しようとするものを作成する際のオーバーヘッドは、結果に見合う価値がないためです。
  • Cを使用する必要がある場合は、作業をできるだけ簡単にする手段を検討してください(offsetof演算子と、オフセット0から始まる最初のメンバーのようなプロパティ構造体があることを考慮してください)。

リンクリストなどの特定のデータ構造をシリアル化/逆シリアル化するのにかかる開発時間を短縮したいと思います。安心してください、あなたがやろうとしていることは些細なことではなく、それはもっと多くの仕事です。そうすることを主張する場合は、オペレーティングシステムのメモリ管理コードとOSのページングメカニズムを調べることを検討してください。;-)

追加された質問による編集:あなたが述べるデザインは、ある種のステートマシンのように聞こえます。オブジェクトのプロパティは、シリアル化できるように設定されており、関数ポインタを復元できます。

まず、オブジェクトのスレッド状態について:競合状態などの一般的な並行プログラミングの問題が発生する可能性がある場合にのみ問題になります。その場合は、ミューテックス、セマフォなどのスレッド同期機能が必要です。次に、次のことができます。いつでもプロパティにアクセスして、シリアル化/逆シリアル化して安全を確保してください。

第二に、オブジェクトのセットアップに関して:見た目はかっこいいですが、バイナリまたは他のオブジェクト表現があるかどうかはわかりません。バイナリを想定すると、メモリ内の実際の構造を表すことができれば、それらを簡単にシリアル化できます(これはコーディングのオーバーヘッドが少しあります)。オブジェクトの先頭にある種のクラスID値を挿入し、実際の衣装を指すルックアップテーブルを作成します。最初のsizeof(id)バイトを見ると、どの種類の構造体があるかがわかります。次に、どの構造がそこに配置されているかがわかります。

シリアル化/逆シリアル化するときは、次のような問題に取り組みます。仮想的にパックされた(メンバー間にスペースがない)構造の長さを調べ、そのサイズを割り当て、メンバーを次々に読み取り/書き込みできます。offsetofを考えるか、コンパイラがそれをサポートしている場合は、パックされた構造体を使用してください。

大胆なコア質問のために編集:-)いいえ、ありません。C用ではありません。

于 2008-10-08T18:22:22.717 に答える
0

C++でクロージャが必要なようです。ご指摘のとおり、これを可能にするメカニズムは言語に組み込まれていません。私の知る限り、これを完全に一般的な方法で行うことは基本的に不可能です。一般に、VMがない言語で行うのは困難です。基本的に実行環境/状態を維持するクロージャーオブジェクトを作成することを提案したようなことをすることで、それをいくらか偽造することができます。次に、既知の状態にあるときに、これをシリアル化します。

また、関数ポインタで問題が発生します。関数は、ロードごとに異なるメモリアドレスにロードできます。

于 2008-10-08T18:22:53.450 に答える
0

JSR 323 で Java に対して実際に提案されたのは、次のようなものです。

http://tech.puredanger.com/2008/01/09/strong-mobility-for-java/

しかし、あまりにも理論的であるとして受け入れられませんでした:

http://tech.puredanger.com/2008/01/24/jcp-votes-down-jsr-323/

リンクをたどると、この問題に関する興味深い研究を見つけることができます。

于 2008-10-08T21:47:51.133 に答える
0

スレッドの状態は実装の詳細であり、おそらくシリアル化するのは適切ではないと考えています。オブジェクトの状態を保存する必要があります。必ずしもオブジェクトがどのようになったかではありません。

このアプローチを採用する理由の例として、ヒットレス アップグレードを考えてみましょう。アプリケーションのバージョン N を実行していて、バージョン N+1 にアップグレードする場合は、オブジェクトのシリアル化を使用してアップグレードできます。ただし、「バージョン N+1」のスレッドは、バージョン N のスレッドとは異なります。

于 2008-10-08T18:58:10.977 に答える