Erlang 핫 배포 – 모듈 업데이트
3815 단어 erlang
-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 명령의 역할은 지정된 모듈을 컴파일하고 불러오는 것이다)
Hello: Hello가 Hello의 글씨를 출력합니다. 하지만, 만약 우리가 지금 Hi를 출력하고 싶다면, Hello가 아니라 Hi를 출력하고 싶다면 어떻게 해야 합니까?자바에서는 일반적으로 프로그램을 다시 컴파일하고 실행해야 하지만, 이전의 실행 상태도 잃어버리고 (dict에 저장된name) init 방법을 다시 실행해야 합니다.
Hello를 Hi로 바꾸고 같은 컨트롤러에서 Hello: Hello (Hello: init 호출되지 않음) 를 직접 호출합니다. 결과가 어떻게 되는지 보십시오.
4> c(hello).
{ok,hello}
5> hello:hello(Db).
hi: "jzh"!
ok
코드 업데이트 후 하이 텍스트를 출력하는 것을 볼 수 있습니다. (dict에 저장된name은 새 코드의 불러오기 때문에 효력을 잃지 않습니다.)
위의 예에서 볼 수 있듯이 Erlang은 런타임 상태(데이터)에 영향을 주지 않고 런타임 시 코드를 교체할 수 있습니다.Java에서 유사한 기능을 완성하는 것은 비교적 어렵다. 그렇다면 Erlang 뒤에서 이런 기능을 실현하는 원리는 무엇일까?원래, 어느 때든지 하나의 모듈은 두 가지 버전을 실행할 때 시스템에 불러올 수 있다. 하나는 낡은 버전, 하나는 현재 버전이다.모듈을 불러올 때, 실행할 때 시스템은 먼저 이 모듈에 이미 코드가 존재하는지 확인하고, 만약 존재한다면, 이미 존재하는 코드를 낡은 코드로 하고, 새로 불러온 코드를 현재 버전으로 한다.만약 세 번째 코드가 시스템에 불러오면 원래의 구 버전 코드는 삭제되고 이 버전 코드와 관련된 모든 프로세스가 끝납니다.원래의 현재 코드가 현재의 구 버전 코드로 바뀌고 세 번째 코드가 현재 버전이 된다.
함수 호출에는 두 가지 방식이 있다. 하나는 완전 한정 호출(Mod:Func)이다. 모듈 내, 모듈 간 이런 방식의 호출을 포함하고 모듈 간에import 명령을 통해 다른 모듈을 가져오고 함수 이름을 통해 직접 호출한다.모듈 내에만 존재하는 함수 호출(Func)완전히 제한된 함수 호출은 항상 현재 버전 코드를 인용합니다.구 버전 코드는 직접 호출을 통해서만 인용될 수 있습니다.
-module(m).
-export([loop/0]).
loop() ->
receive
code_switch ->
m:loop();
Msg ->
...
loop()
end.
위 코드와 같이 코드 업데이트가 있고 프로세스에 코드가 없습니다switch 메시지, 그러면 프로세스는loop 호출을 통해 구 버전 코드를 계속 인용합니다.코드switch 메시지 후 프로세스는 m:loop을 통해 현재 버전 코드를 인용합니다.
(이 부분은 Erlang 프로그래밍 가이드 소프트웨어 업그레이드 1장으로 원리에 대해 약간 복잡하게 설명했다)
가상 머신의 실현 측면에서 볼 때 이 두 가지의 차이는 어디에 있습니까?다음 코드를 살펴보십시오.
-module(test).
-import(hello, [hello/0]).
test2() ->
ok.
test() ->
test2(),
test:test2(),
hello(),
hello:hello(),
ok.
테스트 함수에서 생성된 opcode를 살펴보겠습니다.
i_call_f test:test2/0
i_call_ext_e test:test2/0
i_call_ext_e hello: hello/0
i_call_ext_e hello: hello/0
테스트 2를 직접 호출하여 생성한opcode는 icall_f, 다른 모든 한정 호출 (hello () 호출 포함) 은 icall_ext_e 명령어.이 둘은 어떤 차이가 있습니까?i_call_f 명령은 해당 함수의 입구(프로세스 생성 후 주소가 확정됨)로 바로 이동하여 실행되며, icall_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/emulatort/emulatort/beam/beam/Export.] 구조를 통해 정의됩니다.이전 버전의 코드를 인용하는 프로세스가 없으면 모듈이 업데이트된 후에 다른 프로세스는 그 어떠한 방식으로도 이전 버전의 코드를 인용할 수 없습니다. (모듈 내보내기 함수 목록의 주소가 업데이트되었습니다.)
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Instalando o Elixir e o Erlang com o gerenciador de versões asdfEsse tutorial usa o gerenciador de versões asdf, mas fique a vontade para utilizar outros se preferir. Infelizmente o as...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.