变更特殊进程的代码
在这种情况下,简单代码替换是不够的。当特殊进程的驻留模块的新版本被加载后,进程必须对它的循环函数进行一个完全合格的调用来切换到新的代码上。这样就必须使用同步代码替换。
Note
对于特殊进程,用户定义的驻留模块的名称必须列在子进程规格的 Modules 中,以便发布处理器能找到该进程。
例如。想一下 sys和proc_lib 一章中的例子 ch4 。当通过督程启动的时候,子进程规格应如:
- {ch4, {ch4, start_link, []},
- permanent, brutal_kill, worker, [ch4]}
如果 ch4 是应用 sp_app 中的一部分,并且当该应用从版本“1”升级到“2”的时候,要载入 ch4 的一个新版本,则 sp_app.appup 应如:
- {"2",
- [{"1", [{update, ch4, {advanced, []}}]}],
- [{"1", [{update, ch4, {advanced, []}}]}]
- }.
update 指令必须包含元组 {advanced,Extra} 。该指令将让特殊进程调用回调函数 system_code_change/4 ,用户必须实现该函数。表达式 Extra ,在这里是 [],会被原样传递给 system_code_change/4 :
- -module(ch4).
- ...
- -export([system_code_change/4]).
- ...
- system_code_change(Chs, _Module, _OldVsn, _Extra) ->
- {ok, Chs}.
第一个参数是内部状态 State ,来自函数 sys:handle_system_msg(Request,From,Parent,Module,Deb,State) ,当特殊进程接受到一个系统消息的时候由特殊进程调用该函数。在 ch4 中,内部状态是可用频道的集合 Chs 。
第二个参数是模块的名字( ch4 )。
第三个参数是 Vsn 或者 {down,Vsn} ,和 gen_server:code_change/3 中描述的一样。
在这里,所有参数除了第一个外都被忽略了,同时函数仅仅直接返回内部状态。如果代码只是被扩展了下,那么这样就够了。如果我们还想更改内部状态(类似于在 变更内部状态 中的例子),就可以在这个函数中进行,并返回 {ok,Chs2} 。