在erlang热代码替换 [英] Hot code replacement in erlang
问题描述
gen_fsm
这样的行为是免费的。虽然这可能会达到这个结果,我想用这个来学习如何做,而不仅仅是完成。我已阅读有关代码替换的文档,以及LYSE关于<一个href =http://learnyousomeerlang.com/designing-a-concurrent-application#hot-code-loving =noreferrer> Hot Code Loving ,除此之外,我还没有能够找到适合我正在做的事情,所以这里是基本的想法。 -module(重新加载)。
-export([loop / 0])。
loop() - >
收到
升级 - >
?MODULE:loop();
hello - >
io:format(这是一个测试〜n),
loop();
_ - >
loop()
结束。
我只是循环发送消息 upgrade
,它将加载较新版本的代码。
$ erl
Erlang R15B01 erts-5.9.1)[source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.1(中止与^ G)
1> C(重装)。
{ok,reloading}
2> Loop = spawn(reloading,loop,[])。
< 0.39.0>
3>循环!你好。
这是一个测试
hello
此时我将10行更改为 io:format(我已经改变了!〜n),
4>循环!升级。
升级
5>循环!你好。
这是一个测试
hello
我期待这个 hello
调用打印我已经改变了这个!
不是这是一个测试
。我知道我可以简单地调用 c(重新加载)。
并且这样工作的方式是预期的,但我正在寻找发送实际项目的消息,而不是手动更新代码。那么我的断开在哪里?我做错了什么,我应该做的是为了加载这个代码?如前所述,为了教育,我正在寻找一种非OTP解决方案。
为了有一个明确的答案,我发布了这个。
使用 @rvirding
建议使用代码模块,我修改了它,如下所示:
- 模(重装)。
-export([loop / 0])。
loop() - >
收到
升级 - >
代码:purge(?MODULE),
编译:文件(?MODULE),
代码:load_file(?MODULE),
?MODULE:loop();
hello - >
io:format(这是一个测试〜n),
loop();
_ - >
loop()
结束。
首先代码: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(中止与^ G)
1> Loop = spawn(reloading,loop,[])。
< 0.34.0>
2>循环!你好。
这是一个测试
hello
将行更改为 io:format(我已经改变了!〜n),
3>循环!升级。
升级
4>循环!你好。
我已经改变了这个!
hello
I am working on my first real project in erlang, however, this code is simplified for brevity. I want to be able to load a newer version of a file into my project remotely while it's running. I've read about using a behavior like gen_server
or gen_fsm
which has this for free. While that might achieve the result, I want to use this to learn how to do it, not just get it done. I've read the docs about code replacement, and LYSE's bit about Hot Code Loving, among other things, but I haven't been able to find anything that works for what I'm doing, so here is the basic idea.
-module(reloading).
-export([loop/0]).
loop() ->
receive
upgrade ->
?MODULE:loop();
hello ->
io:format("This is a test~n"),
loop();
_ ->
loop()
end.
I am simply looping with the idea that I can send the message upgrade
and it will load a newer version of the code.
$ 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
At this point I change 10 line to io:format("I have changed this!~n"),
4> Loop ! upgrade.
upgrade
5> Loop ! hello.
This is a test
hello
I am expecting this hello
call to print I have changed this!
not This is a test
. I know I can simply call c(reloading).
and have this work the way expected, but I'm looking to send the actual project a message rather than manually updating the code. So where is my disconnect? What am I doing wrong, that I should be doing in order to hot load this code? As mentioned before, I am looking for a non-OTP solution for the sake of education.
For the sake of having an explicit answer, I am posting this.
Using @rvirding
's suggestion of using the code module, I've modified it to look like this:
-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.
First code:purge the old ?MODULE
, then compile:file the new file, and finally, code:load_file the new ?MODULE
.
This works as I originally intended.
$ 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
Change line to io:format("I have changed this!~n"),
3> Loop ! upgrade.
upgrade
4> Loop ! hello.
I have changed this!
hello
这篇关于在erlang热代码替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!