日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

再谈Erlang代码热替换

發布時間:2025/4/5 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 再谈Erlang代码热替换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Erlang一個非常值得稱道的特性就是代碼熱替換(Hot Code Sawpping),我們在調用函數時,通過M:F(A)的方式,可以保證總是加載最新的代碼。

在《Erlang程序設計》中E4部分,通過一個小例子展示了代碼的動態加載,兩個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內部,當有新的Module被調用時,舊的Module的Export 函數將被新的Export函數代替,因此當我們實用M:F(A)的方式調用函數時,將調用最新代碼。

    讓我們啟動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).
    現在在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,產生了一個錯誤信息,返回{error,not_purged},現在已經有Vsn1,Vsn2兩個a module了,這第三個被拒絕了。我們必須調用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已經被kill了,現在只有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的運行時,判斷當前函數是否為old
    請注意:code:purge 和 code:soft_purge 針對的是old version,如果當前module只有一個version,那么 purge返回false, soft_purge返回true.

    轉載于:https://www.cnblogs.com/xiayong123/archive/2012/01/15/3717159.html

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的再谈Erlang代码热替换的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。