之前看到 Erlang 中的注冊進程時,對注冊并不理解,主要是不理解注冊的原子的作用域。剛才突然想明白了:
Erlang 中的并發(fā)機制是通過消息郵箱實現(xiàn)的,進程間進行通訊的方式只有消息郵箱,而進程間通訊需要知道進程的進程號,而使用 spawn 產(chǎn)生新進程時會返回新進程的進程號供使用。
一個最簡單的進程間通信的程序如下
start() ->
spawn(?MODULE, loop, []).
loop() ->
io:format("Waiting for new message.~n"),
receive
M -> io:format("New message: ~p~n", [M])
end,
loop().
在 Erlang Shell 中使用 c(test) 編譯這個模塊,之后就可以簡單的使用了.
在下面的代碼中,語句前面的注釋表示解釋,語句后面的注釋表示輸出值, % => 后面的值表示語句的返回值
% 開啟無限循環(huán)
Pid = test:start().
% Waiting for new message. % 新進程 spawn 后立刻運行
% => 0.35.0> % 返回新進程的進程號
% 向進程發(fā)送消息
Pid ! 'message'.
% New message: message % 接收到消息
% Waiting for new message. % 繼續(xù)接收消息
% => message % 語句返回值,而非進程返回消息
但是這樣寫還有個明顯的弊端,調(diào)用 call 時需要 Pid 參數(shù),但是又不能去掉,因為需要進程號才能通信,所以使用時需要用戶維護一個進程號。
而 Erlang 提供了注冊進程的機制用來把原子關聯(lián)到進程中,可以解決這個問題
使用 register(atom, Pid) 可以將 atom 關聯(lián)到進程號為 Pid 的進程上,這個原子就
修改上面的 start 函數(shù)為
start() ->
register(testp, spawn(?MODULE, loop, [])).
loop() ->
io:format("Waiting for new message.~n"),
receive
M -> io:format("New message: ~p~n", [M])
end,
loop().
call(M) ->
testp ! M.
register(atom, Pid).
% 取消 atom 的注冊
unregister(atom).
% 返回 atom 關聯(lián)的進程號,如果未關聯(lián),返回 undefined
whereis(atom).
% 返回系統(tǒng)中所有已注冊的進程名
registered().