この節では登録済みプロセスというものを扱います。
今まで、別のプロセスにメッセージを送信するには
Pid ! Message
とやらなくてはいけませんでした。
つまり、
「Pidを知っていなければ通信することはできない」
ということです。
安全と言えば安全なのですけど、ちょっと不便かもしれませんね。
しかし、実はプロセスを登録するということが可能で、 それを行なうことにより、登録されたプロセスに対してどのプロセスからも簡単に通信を行うことができるようになります。
登録の仕方は
register(Atom,Pid)
とするだけです。Atomはアトムで、Pidはプロセス識別子です。
それでは、プログラムを通して学んでみましょう。
-module(server).
-export([start1/0,start2/0]).
start1() ->
spawn(fun() -> loop() end).
start2() ->
spawn(fun() -> reg() end).
reg() ->
register(serv2,self()),
loop().
loop() ->
receive
{add,X,Y} ->
io:format("~p + ~p = ~p~n",[X,Y,X+Y]),
loop();
{mul,X,Y} ->
io:format("~p * ~p = ~p~n",[X,Y,X*Y]),
loop()
end.
start1/0は普通に新しくプロセスを生成しています。
start2/0はプロセスを生成すると同時に登録しています。
実行してみましょう
自分のプロセス内で、別のプロセスを登録している。
1> register(serv1,server:start1()).
true
2> serv1 ! {add,3,9}.
3 + 9 = 12
{add,3,9}
自分のプロセス内では、別のプロセスを登録していない。
3> server:start2().
<0.36.0>
4> serv2 ! {mul,4,12}.
4 * 12 = 48
{mul,4,12}
アトム serv1 はシェルのプロセスで登録しています。 したがって、serv1というアトムと、作成されたプロセスの対応付けが可能なのは分かります。
重要なのは serv2 です。
これは新しくプロセスを作成し、そのプロセス内で登録されていますね。シェルのプロセスで登録されているのではありません。
それなのに、シェルのプロセスで serv2 ! {mul,4,12} と利用されています。
つまり、登録されたプロセスであれば、プロセス識別子を知らないプロセスからもアトムを指定するだけで通信が可能だということです。
最後に登録済みプロセスで使える関数を見ていきます。
どれも良く利用されるものなので、覚えておくといいと思います。
関数(BIF erlang) | 役割 |
---|---|
register(Atom,Pid) | プロセスID PidをアトムAtomとして登録する。登録されている場合は失敗する。 対応付けられたプロセス名は同一環境内なら利用することが可能である。 |
unregister(Atom) | Atomに対応する登録を削除する。登録されていなければ例外を投げる |
whereis(Atom) | Atomで登録されているPidを返す。登録されていなければundefinedが返される |
registered() | 登録されているアトムをリストで返す |
なお、登録されているプロセスが終了した場合は、アトムとプロセスの対応付けは自動的に解消されます。
1> register(serv1,server:start1()).
true
2> whereis(serv1).
<0.33.0>
3> serv1 ! {add,5,4}.
5 + 4 = 9
{add,5,4}
4> whereis(serv1).
<0.33.0>
5> unregister(serv1).
true
6> whereis(serv1).
undefined
7> server:start2().
<0.40.0>
8> registered().
[application_controller,kernel_sup,global_name_server,
file_server_2,code_server,user,serv2,init,error_logger,
inet_db,global_group,kernel_safe_sup,erl_prim_loader,rex]
registered()の結果を見ると、システムによりいくつかが既に登録されていることが分かりますね。 よく見ると、リストの中にきちんとserv2もあります。