20

私は erlang で最初の実際のプロジェクトに取り組んでいますが、このコードは簡潔にするために単純化されています。プロジェクトの実行中に、新しいバージョンのファイルをプロジェクトにリモートでロードできるようにしたいと考えています。gen_serverまたはのような動作を無料で使用することについて読んだことがgen_fsmあります。それは結果を達成するかもしれませんが、私はこれを使ってそれを成し遂げるだけでなく、それを行う方法を学びたいと思っています. 私はコード置換に関するドキュメントや、LYSE のHot Code Lovingに関するビットなどを読みましたが、私がやっていることのために機能するものを見つけることができなかったので、ここに基本的な考え方があります。

-module(reloading).

-export([loop/0]).

loop() ->
    receive
        upgrade ->
            ?MODULE:loop();
        hello ->
            io:format("This is a test~n"),
            loop();
        _ ->
            loop()
    end.

メッセージを送信できupgrade、新しいバージョンのコードが読み込まれるという考えで単純にループしています。

$ erl
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.1  (abort with ^G)
1> c(reloading).
{ok,reloading}
2> Loop = spawn(reloading, loop, []).
<0.39.0>
3> Loop ! hello.
This is a test
hello

この時点で、10行を次のように変更しますio:format("I have changed this!~n"),

4> Loop ! upgrade.
upgrade
5> Loop ! hello.  
This is a test
hello

helloこの呼び出しが print I have changed this!notになることを期待していThis is a testます。単純に呼び出しc(reloading).て、これを期待どおりに動作させることができることはわかっていますが、コードを手動で更新するのではなく、実際のプロジェクトにメッセージを送信したいと考えています。それで、私の切断はどこですか?このコードをホットロードするために何をすべきでしょうか? 前に述べたように、私は教育のために OTP 以外のソリューションを探しています。

4

4 に答える 4

24

明確な答えを得るために、私はこれを投稿しています。

コードモジュールを使用するという の提案を使用して、次のように変更しました@rvirding

-module(reloading).

-export([loop/0]).

loop() ->
    receive
        upgrade ->
            code:purge(?MODULE),
            compile:file(?MODULE),
            code:load_file(?MODULE),
            ?MODULE:loop();
        hello ->
            io:format("This is a test~n"),
            loop();
        _ ->
            loop()
    end.

最初に古いファイルをcode:purge?MODULEし、新しいファイルをcompile:fileして、最後に新しいファイルをcode:load_file?MODULEます。これは、当初の意図どおりに機能します。

$ erl
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.1  (abort with ^G)
1> Loop = spawn(reloading, loop, []).
<0.34.0>
2> Loop ! hello.
This is a test
hello

行を次のように変更io:format("I have changed this!~n"),

3> Loop ! upgrade.                   
upgrade
4> Loop ! hello.  
I have changed this!
hello
于 2012-08-15T15:10:59.487 に答える
19

erlang は 2 つのバージョンのモジュールを扱うことができ、 で関数を呼び出すmod:func(...)と常にモジュールの最新バージョンが呼び出されますが (関数がエクスポートされている場合)、モジュールの新しいバージョンを Erlang システムにロードする必要があります。モジュールの新しいバージョンがたまたまどこかにあることを自動的に検出し、それを見つけてコンパイルし、ロードすることを期待することはできません。

注:コンパイルとロードは 2 つの別個のものです。したがって、モジュールのコンパイルロードのc(mod). 両方が行われますが、コンパイル済みのモジュールのオブジェクト コード (.beam ファイル) のみがロードされます。Erlang コンパイラはモジュールから呼び出され、コードのロードがモジュールによって処理されている間、コンパイルして .beam ファイルを生成するだけです。l(mod).compilecode

于 2012-08-15T12:42:00.783 に答える
1

上記に加えて、コードを自動的にリロードするツールがいくつか存在することに注意してください。

同期またはアクティブなプロジェクトを確認する必要があります。

于 2015-09-24T19:35:45.017 に答える