首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Erlang暖部署 – 模块更新

2012-12-27 
Erlang热部署 – 模块更新Erlang的热部署做的很完善,参见ReleaseHandling,这篇文章只关心最基本的模块更新。

Erlang热部署 – 模块更新

Erlang的热部署做的很完善,参见ReleaseHandling,这篇文章只关心最基本的模块更新。模块是Erlang程序组织的最基本单元。如下代码就是一个最简单的hello模块(为了说明问题,我们添加了一个init函数):

?

-module(hello).-export([init/0, hello/1]).init() ->    Db = dict:new(),    dict:store(name, "jzh", Db).hello(Db) ->    Value = dict:fetch(name, Db),io:format("hello: ~p!~n", [Value]).

?

?运行一下:

?

1> c(hello).{ok,hello}2> Db = hello:init().{dict,1,16,16,8,80,48,      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}      {{[],[],[],[],[],        [[name,106,122,104]],        [],[],[],[],[],[],[],[],[],[]}}}3> hello:hello(Db).hello: "jzh"!ok

?(c命令的作用是编译和加载指定模块)

?

4> c(hello).{ok,hello}5> hello:hello(Db).hi: "jzh"!ok

?可以看到,代码更新后打印出hi字样(保存在dict中的name,并没有因为新代码的加载而失效)。

?

-module(m).-export([loop/0]).loop() -> receive code_switch -> m:loop(); Msg -> ... loop() end.

?如上代码,如果有代码更新,并且进程没有收到code_switch消息,那么进程就会通过loop调用一直在引用旧版本代码;而收到code_switch消息后,进程便通过m:loop引用到当前版本代码。

?

-module(test).-import(hello, [hello/0]).test2() ->ok.test() ->test2(),test:test2(),hello(),hello:hello(),ok.

?

?我们来看看test函数生成的opcode:

?

i_call_f test:test2/0i_call_ext_e test:test2/0i_call_ext_e hello: hello/0i_call_ext_e hello: hello/0

可以看出,直接调用test2生成的opcode是i_call_f,而其它的全限定调用(包括hello()调用)都生成的是i_call_ext_e指令。这两者有什么区别?i_call_f指令会直接跳到相应函数的入口(进程生成后,地址确定)并执行,而i_call_ext_e会根据模块导出函数列表中的地址跳转(详见[$OTP_SRC/erts/emulator/beam/beam_emu.c -->process_main)。这个地址在模块更新时会更新为当前版本代码导出函数的地址(详见[$OTP_SRC/erts/emulator/beam/beam_bif_load.c -->load_module_2] ,导出函数地址通过[$OTP_SRC/erts/emulator/beam/export.h]中Export结构的address定义)。从这里也可以看出来,除非有进程在引用旧版本的代码,模块更新后,其它进程是无法再通过任何方式引用到旧版本的代码(模块导出函数列表中的地址已更新)。

?

热点排行