浏览 4265 次
锁定老帖子 主题:再谈Erlang代码热替换
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-01-14
最后修改:2009-05-19
在《Erlang程序设计》中E4部分,通过一个小例子展示了代码的动态加载,两个module代码如下: a.erl -module(a). -compile(export_all). -import(b, [x/0]). start(Tag) -> spawn(fun() -> loop(Tag) end). loop(Tag) -> timer:sleep(3000), Val = x(), io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]), loop(Tag). b.erl -module(b). -compile(export_all). x() -> 1. 这个例子中是通过c(a), c(b)的方式编译修改后的a.erl 和 b.erl,这里其实是做了两件事: 1,编译module 2,load module 所以我们在这个例子中,可以看到如果我们修改了b的代码,然后在Erlang shell中通过: c(b). 我们可以立即看到“新”的b module在运行了。 在Erlang中每个Module可以保存2个version,如果再有第三个version加入,那么首先要通过code:purse/1清理先前的版本,随后才可以load新的module。 在Erlang内部,当有新的Module被调用时,旧的Module的Export 函数将被新的Export函数代替,因此当我们实用M:F(A)的方式调用函数时,将调用最新代码。 让我们启动a module: > a:start(one). Vsn1 (one) b:x() = 1 随后我们修改a.erl: -io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]), +io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]), 然后编译a.erl: $ erlc a.erl 当前,在Erlang中只有Vsn1版本的a,回到erlang shell中,加载Vsn2: > code:load_file(a). 现在在Erlang中有Vsn1和Vsn2两个版本的a module。 我们在启动一个新的a process: > a:start(two). Vsn2 (two) b:x() =1 好了让我们再次修改a.erl: -io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]), +io:format("Vsn3 (~p) b:x() = ~p~n", [Tag, Val]), 然后编译a.erl: $ erlc a.erl 注意:此时Erlang shell中并没有加载Vsn3版本的代码,因为我们没有使用c(a)的方式编译加载a module。我们可以测试一下: >a:start(three). <0.38.0> Vsn2 (three) b:x() = 1 毫无疑问,还是Vsn2 接下来我们想加载Vsn3版本的a,回到Erlang shell: > code:load_file(a). =ERROR REPORT==== 14-Jan-2009::23:16:23 === Loading of /home/litao/erl/a.beam failed: not_purged {error,not_purged} =ERROR REPORT==== 14-Jan-2009::23:16:23 === Module a must be purged before loading oh,产生了一个错误信息,返回{error,not_purged},现在已经有Vsn1,Vsn2两个a module了,这第三个被拒绝了。我们必须调用code:purge/1清除Vsn1: > code:purge(a). true Vsn2 (three) b:x() = 1 Vsn2 (two) b:x() = 1 返回true,同时Vsn1版本的a process已经被kill了,现在只有Vsn2了。接下来加载我们的Vsn3吧: > code:load_file(a). {module,a} Vsn2 (two) b:x() = 1 Vsn2 (three) b:x() = 1 8> a:start(five). <0.43.0> Vsn2 (three) b:x() = 1 Vsn2 (two) b:x() = 1 Vsn3 (five) b:x() = 1 好了Vsn2成了旧版本,Vsn3成了新版本。 自己动手实验一下吧! Update: code:soft_purge(Module),如果没有process运行旧的Module,则返回true(表明此Module可以被温和的purge);否则返回false。 可以通过erlang:check_process_code(Pid, Module)检测Process是否运行某个Module的Old version,这个检测不会检测process的运行时,判断当前函数是否为old 请注意:code:purge 和 code:soft_purge 针对的是old version,如果当前module只有一个version,那么 purge返回false, soft_purge返回true. 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-01-15
恩, 又加深一遍印象, 加油
|
|
返回顶楼 | |
发表时间:2009-01-16
可以再研究下动态库模块代码热替换!
|
|
返回顶楼 | |
发表时间:2009-02-24
好文字.
litaocheng 写道 Erlang一个非常值得称道的特性就是代码热替换(Hot Code Sawpping),我们在调用函数时,通过M:F(A)的方式,可以保证总是加载最新的代码。
在《Erlang程序设计》中E4部分,通过一个小例子展示了代码的动态加载,两个module代码如下: a.erl -module(a). -compile(export_all). -import(b, [x/0]). start(Tag) -> spawn(fun() -> loop(Tag) end). loop(Tag) -> timer:sleep(3000), Val = x(), io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]), loop(Tag). b.erl -module(b). -compile(export_all). x() -> 1. 这个例子中是通过c(a), c(b)的方式编译修改后的a.erl 和 b.erl,这里其实是做了两件事: 1,编译module 2,load module 所以我们在这个例子中,可以看到如果我们修改了b的代码,然后在Erlang shell中通过: c(b). 我们可以立即看到“新”的b module在运行了。 在Erlang中每个Module可以保存2个version,如果再有第三个version加入,那么首先要通过code:purse/1清理先前的版本,随后才可以load新的module。 在Erlang内部,当有新的Module被调用时,旧的Module的Export 函数将被新的Export函数代替,因此当我们实用M:F(A)的方式调用函数时,将调用最新代码。 让我们启动a module: > a:start(one). Vsn1 (one) b:x() = 1 随后我们修改a.erl: -io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]), +io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]), 然后编译a.erl: $ erlc a.erl 当前,在Erlang中只有Vsn1版本的a,回到erlang shell中,加载Vsn2: > code:load_file(a). 现在在Erlang中有Vsn1和Vsn2两个版本的a module。 我们在启动一个新的a process: > a:start(two). Vsn2 (two) b:x() =1 好了让我们再次修改a.erl: -io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]), +io:format("Vsn3 (~p) b:x() = ~p~n", [Tag, Val]), 然后编译a.erl: $ erlc a.erl 注意:此时Erlang shell中并没有加载Vsn3版本的代码,因为我们没有使用c(a)的方式编译加载a module。我们可以测试一下: >a:start(three). <0.38.0> Vsn2 (three) b:x() = 1 毫无疑问,还是Vsn2 接下来我们想加载Vsn3版本的a,回到Erlang shell: > code:load_file(a). =ERROR REPORT==== 14-Jan-2009::23:16:23 === Loading of /home/litao/erl/a.beam failed: not_purged {error,not_purged} =ERROR REPORT==== 14-Jan-2009::23:16:23 === Module a must be purged before loading oh,产生了一个错误信息,返回{error,not_purged},现在已经有Vsn1,Vsn2两个a module了,这第三个被拒绝了。我们必须调用code:purge/1清除Vsn1: > code:purge(a). true Vsn2 (three) b:x() = 1 Vsn2 (two) b:x() = 1 返回true,同时Vsn1版本的a process已经被kill了,现在只有Vsn2了。接下来加载我们的Vsn3吧: > code:load_file(a). {module,a} Vsn2 (two) b:x() = 1 Vsn2 (three) b:x() = 1 8> a:start(five). <0.43.0> Vsn2 (three) b:x() = 1 Vsn2 (two) b:x() = 1 Vsn3 (five) b:x() = 1 好了Vsn2成了旧版本,Vsn3成了新版本。 自己动手实验一下吧! |
|
返回顶楼 | |