如何在动态管理程序中自动删除已终止子项的规范

时间:2011-03-12 21:41:49

标签: erlang otp supervisor

对于这个问题不需要USB知识,只是将其描述为使示例更加清晰。

我正在尝试为USB总线上的特定设备实现动态管理程序。 这些设备具有地址,并在系统的生命周期内出现和消失。

对于每个设备,我需要为我的主管提供一个动态的孩子。

这些孩子是短暂的,所以一旦他们崩溃或终止,我们就不会重新启动它们(因为可能它们已经消失了)。

我有一个过程会在特定时间扫描USB端口,并生成一个我想要处理的USB设备的所有地址列表。

我打算在每次扫描之前调用supervisor:which_children/1以找出存在哪些设备但没有运行子进程。

为了找出哪些地址有子运行我计划为包含地址的childspec创建Id原子(只有几个地址可能),例如如果孩子处理地址adr_12,则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是否还返回已经终止的孩子。

因此,如果孩子们在短暂终止后会被删除,那将是最好的。

不知何故,这一切对我来说都不优雅,所以我问自己(和你):

我怎样才能最优雅地解决这个问题?

在这种情况下,最好不要使用主管吗?

2 个答案:

答案 0 :(得分:2)

我的直觉/膝跳反应是:'你需要为他们使用一个simple_one_for_one'主管,所以他们的规格在停止时会被移除。如果您需要能够获取特定的通信过程,我会使用 gproc 应用程序(或ETS表)。

答案 1 :(得分:1)

听起来我想要动态添加到主管的孩子彼此非常相似。也许你需要simple-one-for-one主管。这些主管是“one_for_one主管的简化版本,其中所有子进程都是动态添加同一进程的实例。”每个孩子都有相同的子规格,因此您在拨打supervisor:add_child/2时无需指定。

另外,请注意上述动态创建原子(例如adr_12)的想法可能很危险。 Erlang系统中的原子是有限的(默认为~1000000)。有关详细信息,请参阅文档。