プロセス追跡とエラー処理、パート3

前文



前のパート( パート1パート2 )では、プロセスとエラーを伝播するプロセスとの間に双方向の関係を作成するメカニズムを完全に検討しました。 この記事では、かなり単純な監視メカニズムと、プロセスの操作に関連するいくつかの側面を分析します。



モニター



モニターを操作するための機能


モニターを操作するために必要な機能の小さなリスト:



観察されたプロセスがクラッシュした場合、モニターはメッセージ{'DOWN'、Reference、process、Pid、Reason}を受け取ります。

  1. 'DOWN'-プロセスがクラッシュしたことを意味します。
  2. 参照-モニターへのリンク。
  3. プロセス - プロセスが監視されている(ドキュメントはErlangのプロセスの現在のバージョンは唯一、将来的に何か他のものに結びつけることが監視できることを述べています)。
  4. Pid-落ちたプロセスのPid。
  5. 理由が理由です。




接続とモニターの作成の違いの1つは、存在しないプロセスとの接続を作成しようとすると、呼び出しプロセスが落ち、モニターの場合、メッセージ{'DOWN'、Reference、process、Pid、Reason}をすぐに受け取ることです。 実際に試してみましょう-eshallを実行し、次のコマンドを実行します。



(emacs@aleksio-mobile)1> self(). <0.36.0> (emacs@aleksio-mobile)2> erlang:link(c:pid(0,777,0)). ** exception error: no such process or port in function link/1 called as link(<0.777.0>) (emacs@aleksio-mobile)3> self(). <0.39.0> (emacs@aleksio-mobile)4> flush(). ok (emacs@aleksio-mobile)5> erlang:monitor(process, c:pid(0,777,0)). #Ref<0.0.0.43> (emacs@aleksio-mobile)6> self(). <0.39.0> (emacs@aleksio-mobile)7> flush(). Shell got {'DOWN',#Ref<0.0.0.43>,process,<0.777.0>,noproc} ok (emacs@aleksio-mobile)8>
      
      







最初の行では、シェルのPidを認識してから、現在のプロセスを明らかに存在しないerlang:link(c:pid(0.777.0))に関連付けようとします。その後、シェルがクラッシュし、メッセージキューが空になります。 5番目のコマンドは、erlang:monitor(process、c:pid(0,777,0))関数を呼び出します。この関数は、モニターへのリンクを作成して返します。 Pid = <0.777.0>のプロセスはシェルキューに存在しないため、メッセージ{'DOWN'、#Ref <0.0.0.43>、process、<0.777.0>、noproc}が到着し、プロセス<0.777 .0>はシステムにありません。



モニターに関する知識を統合するための小さなモジュールを作成します。

 -module(testm). -export([start_m/0, stop_m/1, loop/1]). start_m() -> erlang:spawn_monitor(?MODULE, loop, [self()]). stop_m(Ref) -> erlang:demonitor(Ref). loop(Shell) -> receive kill -> exit(kill); reason -> exit("Another reason"); Msg -> Shell ! {get_msg, Msg} end.
      
      







spawn_monitor関数は、本体ループを持つプロセスを作成し、呼び出しプロセス(この例のシェルでは)をモニターにします。



 (emacs@aleksio-mobile)2> {Pid, Ref} = testm:start_m(). {<0.43.0>,#Ref<0.0.0.62>} ###  <0.43.0>,    #Ref<0.0.0.62> (emacs@aleksio-mobile)3> Pid ! hello. hello ###   (emacs@aleksio-mobile)4> flush(). Shell got {get_msg,hello} Shell got {'DOWN',#Ref<0.0.0.62>,process,<0.43.0>,normal} ok ###      {get_msg,hello} ###      normal (emacs@aleksio-mobile)5> f(Pid), f(Ref). ok ###  Pid  Ref  ###    (emacs@aleksio-mobile)6> {Pid, Ref} = testm:start_m(). {<0.48.0>,#Ref<0.0.0.77>} (emacs@aleksio-mobile)7> Pid ! kill. kill (emacs@aleksio-mobile)8> flush(). Shell got {'DOWN',#Ref<0.0.0.77>,process,<0.48.0>,kill} ok (emacs@aleksio-mobile)9> f(Pid), f(Ref). ok (emacs@aleksio-mobile)10> {Pid, Ref} = testm:start_m(). {<0.53.0>,#Ref<0.0.0.91>} (emacs@aleksio-mobile)11> Pid ! reason. reason (emacs@aleksio-mobile)12> flush(). Shell got {'DOWN',#Ref<0.0.0.91>,process,<0.53.0>,"Another reason"} ok (emacs@aleksio-mobile)13> testm:stop_m(Ref). true (emacs@aleksio-mobile)14>
      
      







読者への質問:お気づきのとおり、新しいプロセスが作成されるたびに、モニターへのリンクも新しくなりましたが、最後にモニターをオフにしました。 以前のリンクはプロセスの状態のどこかに残りますか?これは何らかの形で作業に影響しますか?



おわりに



モニター-他のプロセスのステータスを監視するためのかなり便利でシンプルなメカニズムを調べました。 Erlang言語で実装されたタスクに誰もがそれらを適用できることを願っています。



何を読む?



1. 優れたオンラインドキュメント

2. Francesco CesariniとSimon ThompsonによるERLANGプログラミング。

3. RSDNに関する記事: Erlangでのエラー処理



All Articles