2

Erlangで関数をシリアル化し、別のノートに送信し、そこで逆シリアル化して実行する必要があります。私が抱えている問題はファイルにあります。関数が2番目のノードにないファイルから読み取る場合、エラーが発生します。Erlangでシリアル化可能な構造とシリアル化不可能な構造を区別する方法はありますか?したがって、関数がファイルまたはpidを使用する場合、シリアル化に失敗しますか?

ありがとう

4

1 に答える 1

2

まず、匿名関数を送信する場合は、特に注意してください。または、むしろ、それをしないでください

この関数が実行されない場合や、まったく間違った方法で実行される場合がいくつかあります。

Erlangのすべての関数は、匿名の関数であっても、正確には、内部で構築されたモジュールのモジュールに属しています。この関数がREPLに組み込まれている場合、それはerl_evalモジュールにバインドされます。これはさらに危険です(理由についてはさらに説明します)。

たとえば、2つのノードを起動し、そのうちの1つには「foo」という名前のモジュールがあり、もう1つにはそのようなモジュールがロードされていません(ロードできません)。モジュール'foo'内にラムダを作成し、それを2番目のノードに送信して呼び出そうとすると、{error、undef}で失敗します。

別の面白い問題がある可能性があります。モジュール「foo」の2つのバージョンを作成し、それぞれの内部に「bar」関数を実装し、その内部にラムダを実装してみてください(ただし、ラムダは異なります)。送信されたラムダを呼び出そうとすると、さらに別のエラーが発生します。

ラムダを別のノードに送信することには、他にも注意が必要な部分があると思いますが、私を信じてください。それはすでにかなりの量です。

第二に、ラムダ内のプロセスまたはポートを事前に知らなくても取得できる方法はたくさんあります

ラムダからクロージャ変数をキャッチする方法はありますが(2値化されたラムダを見ると、その中で使用されているすべての外部変数は2バイト目からリストされています)、それらは2番目のバイトから始まる唯一のソースではありません。潜在的なpidまたはポート。

簡単な例を考えてみましょうself()。ラムダ内で関数を呼び出します。何が返されますか?そう、ピッド。さて、おそらくバイナリを解析して、他の多数の組み込み関数とともに、この関数呼び出しをキャッチすることができます。しかし、外部関数を呼び出すときはどうしますか?ets:lookup(sometable, somekey)some_module:some_function_that_returns_god_knows_what()?あなたは彼らが何を返すのか分かりません。

さて、ここで実際にできること

  1. ファイルを操作するときは、記述子ではなく、常にファイル名を送信してください。ファイルの位置などが必要な場合は、それも送信してください。ファイル記述子は、開かれたプロセスの外部では認識されるべきではありません。

  2. 前述したように、ラムダが他のノードに送信されないようにすべてを実行します。私はあなたの正確な仕事を知らないので、それを避ける方法を言うのは難しいです。たぶん、あなたは実行する関数のリストを送ることができます、例えば:

    [{module1, parse_query},
     {module1, dispatch_parsed_query},
     {module2, validate_response},
     {module2, serialize_query}]
    

    そして、この関数シーケンスを介して引数を渡します(すべてのモジュールがどこにでも存在することを確認してください)。たぶん、クラスター全体で頻繁に変更および展開されるモジュールに実際に固執することができます。たぶん、JS / Luaに切り替えて、外部で開始されたポートを使用することをお勧めします(Riakはスパイダーモンキーを使用してMap / ReduceリクエストのJSで記述されたラムダを処理しています)。最後に、モジュールのオブジェクトコードを実際に取得し、それを別のノードに送信して、そこにロードすることができます。それも安全ではないことを覚えておいてください。実行中のプロセスを壊したり、構築されたラムダを失ったりする可能性があります。

于 2012-12-04T19:19:37.537 に答える