再谈Erlang代码热替换
生活随笔
收集整理的這篇文章主要介紹了
再谈Erlang代码热替换
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Erlang一個非常值得稱道的特性就是代碼熱替換(Hot Code Sawpping),我們在調(diào)用函數(shù)時,通過M:F(A)的方式,可以保證總是加載最新的代碼。
在《Erlang程序設計》中E4部分,通過一個小例子展示了代碼的動態(tài)加載,兩個module代碼如下:
a.erl
Erlang代碼 ?-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).????? -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
Erlang代碼 ?-module(b). ?? -compile(export_all). ?? ?? x()?->?1.?? -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內(nèi)部,當有新的Module被調(diào)用時,舊的Module的Export 函數(shù)將被新的Export函數(shù)代替,因此當我們實用M:F(A)的方式調(diào)用函數(shù)時,將調(diào)用最新代碼。
讓我們啟動a module:
Erlang代碼 ?>?a:start(one). ?? Vsn1?(one)?b:x()?=?1?? > a:start(one).
Vsn1 (one) b:x() = 1
隨后我們修改a.erl:
Erlang代碼 ?-io:format("Vsn1?(~p)?b:x()?=?~p~n",?[Tag,?Val]), ?? +io:format("Vsn2?(~p)?b:x()?=?~p~n",?[Tag,?Val]),?? -io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]),
+io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]),
然后編譯a.erl:
Erlang代碼 ?$?erlc?a.erl?? $ erlc a.erl
當前,在Erlang中只有Vsn1版本的a,回到erlang shell中,加載Vsn2:
Erlang代碼 ?>?code:load_file(a).?? > code:load_file(a).
現(xiàn)在在Erlang中有Vsn1和Vsn2兩個版本的a module。
我們在啟動一個新的a process:
Erlang代碼 ?>?a:start(two). ?? Vsn2?(two)?b:x()?=1?? > a:start(two).
Vsn2 (two) b:x() =1
好了讓我們再次修改a.erl:
Erlang代碼 ?-io:format("Vsn2?(~p)?b:x()?=?~p~n",?[Tag,?Val]), ?? +io:format("Vsn3?(~p)?b:x()?=?~p~n",?[Tag,?Val]),?? -io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]),
+io:format("Vsn3 (~p) b:x() = ~p~n", [Tag, Val]),
然后編譯a.erl:
Erlang代碼 ?$?erlc?a.erl?? $ erlc a.erl
注意:此時Erlang shell中并沒有加載Vsn3版本的代碼,因為我們沒有使用c(a)的方式編譯加載a module。我們可以測試一下:
Erlang代碼 ?>a:start(three). ?? <0.38.0> ?? Vsn2?(three)?b:x()?=?1?? >a:start(three).
<0.38.0>
Vsn2 (three) b:x() = 1
毫無疑問,還是Vsn2
接下來我們想加載Vsn3版本的a,回到Erlang shell:
Erlang代碼 ?>?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?? > 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,產(chǎn)生了一個錯誤信息,返回{error,not_purged},現(xiàn)在已經(jīng)有Vsn1,Vsn2兩個a module了,這第三個被拒絕了。我們必須調(diào)用code:purge/1清除Vsn1:
Erlang代碼 ?>?code:purge(a). ?? true ?? Vsn2?(three)?b:x()?=?1?? Vsn2?(two)?b:x()?=?1?? > code:purge(a).
true
Vsn2 (three) b:x() = 1
Vsn2 (two) b:x() = 1
返回true,同時Vsn1版本的a process已經(jīng)被kill了,現(xiàn)在只有Vsn2了。接下來加載我們的Vsn3吧:
Erlang代碼 ?>?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?? > 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的運行時,判斷當前函數(shù)是否為old
請注意:code:purge 和 code:soft_purge 針對的是old version,如果當前module只有一個version,那么 purge返回false, soft_purge返回true.
在《Erlang程序設計》中E4部分,通過一個小例子展示了代碼的動態(tài)加載,兩個module代碼如下:
a.erl
Erlang代碼 ?
b.erl
Erlang代碼 ?
這個例子中是通過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內(nèi)部,當有新的Module被調(diào)用時,舊的Module的Export 函數(shù)將被新的Export函數(shù)代替,因此當我們實用M:F(A)的方式調(diào)用函數(shù)時,將調(diào)用最新代碼。
讓我們啟動a module:
Erlang代碼 ?
隨后我們修改a.erl:
Erlang代碼 ?
然后編譯a.erl:
Erlang代碼 ?
當前,在Erlang中只有Vsn1版本的a,回到erlang shell中,加載Vsn2:
Erlang代碼 ?
現(xiàn)在在Erlang中有Vsn1和Vsn2兩個版本的a module。
我們在啟動一個新的a process:
Erlang代碼 ?
好了讓我們再次修改a.erl:
Erlang代碼 ?
然后編譯a.erl:
Erlang代碼 ?
注意:此時Erlang shell中并沒有加載Vsn3版本的代碼,因為我們沒有使用c(a)的方式編譯加載a module。我們可以測試一下:
Erlang代碼 ?
毫無疑問,還是Vsn2
接下來我們想加載Vsn3版本的a,回到Erlang shell:
Erlang代碼 ?
oh,產(chǎn)生了一個錯誤信息,返回{error,not_purged},現(xiàn)在已經(jīng)有Vsn1,Vsn2兩個a module了,這第三個被拒絕了。我們必須調(diào)用code:purge/1清除Vsn1:
Erlang代碼 ?
返回true,同時Vsn1版本的a process已經(jīng)被kill了,現(xiàn)在只有Vsn2了。接下來加載我們的Vsn3吧:
Erlang代碼 ?
好了Vsn2成了舊版本,Vsn3成了新版本。
自己動手實驗一下吧!
Update:
code:soft_purge(Module),如果沒有process運行舊的Module,則返回true(表明此Module可以被溫和的purge);否則返回false。
可以通過erlang:check_process_code(Pid, Module)檢測Process是否運行某個Module的Old version,這個檢測不會檢測process的運行時,判斷當前函數(shù)是否為old
請注意:code:purge 和 code:soft_purge 針對的是old version,如果當前module只有一個version,那么 purge返回false, soft_purge返回true.
轉(zhuǎn)載于:https://www.cnblogs.com/xiayong123/archive/2012/01/15/3717159.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的再谈Erlang代码热替换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2011年中国网络游戏市场实际销售收入达
- 下一篇: 华硕飞行堡垒6怎么重做系统 华硕飞行堡垒