2

この質問には USB の知識は必要ありません。例をより具体的にするために説明しただけです。

USB バス上の特定のデバイスに動的スーパーバイザを実装しようとしています。これらのデバイスにはアドレスがあり、システムの存続期間中に現れたり消えたりします。

デバイスごとに、スーパーバイザーの動的な子が必要です。

これらの子は一時的なものであるため、いったんクラッシュまたは終了すると、再起動しません (おそらくその時点でなくなっているため)。

特定の時間に USB ポートをスキャンし、処理したい USB デバイスのすべてのアドレスのリストを生成するプロセスがあります。

supervisor:which_children/1各スキャンの前に呼び出して、存在するが子プロセスが実行されていないデバイスを見つける予定です。

実行中の子を持つアドレスを見つけるために、アドレスを含む childspec の Id アトムを作成する予定です (可能なアドレスはわずかしかありません)。たとえば adr_12、子が address を処理する場合12です。

行方不明の子を開始/再起動しようとすると、一時的な子が終了またはクラッシュしたときに子仕様が自動的に削除されないというやや醜い状況があります (少なくともそうであると思います)。したがって、次のようなコードが必要になります。

case supervisor:start_child(my_sup, Spec) of
    {error, already_present} ->
        supervisor:restart_child(my_sup, Spec);
    Any -> Any
end

supervisor:which_children/1次に、すでに終了した子供も返すかどうかわからないという問題があります。

そのため、一時的に終了した後に子を削除するのが最善です。

どういうわけか、これはすべて私にとってエレガントではないので、私は自分自身(そしてあなた)に尋ねています:

これを最もエレガントに解決するにはどうすればよいですか?

この状況では、スーパーバイザをまったく使用しない方がよいでしょうか?

4

2 に答える 2

2

私の直感/ひざまずく反応は次のとおりです。「simple_one_for_one を使用する必要があります」スーパーバイザーなので、停止すると仕様が削除されます。通信のために特定のプロセスを取得できるようにする必要がある場合は、そのためにgprocアプリケーション (または ETS テーブル) を使用します。

于 2011-03-12T23:57:36.500 に答える
1

スーパーバイザーに動的に追加したい子供たちは、お互いに非常に似ているように思えます。おそらく、単純な 1 対 1 のスーパーバイザーが必要です。これらのスーパーバイザーは、「すべての子プロセスが同じプロセスのインスタンスを動的に追加する、one_for_one スーパーバイザーの簡略化されたバージョン」です。すべての子は同じ子仕様を持つため、 を呼び出すときにそれを指定する必要はありませんsupervisor:add_child/2

adr_12また、アトム (例: ) を動的に作成するという上記の考え方は危険である可能性があることに注意してください。Erlang システムではアトムは制限されています (デフォルトでは ~1000000)。詳細については、ドキュメントを参照してください。

于 2011-03-12T23:58:09.253 に答える