Как автоматически удалить спецификации завершенных детей в динамическом супервизоре

Для ответа на этот вопрос знание USB не требуется, я просто описал его так, как он есть, чтобы сделать пример более конкретным.

Я пытаюсь реализовать динамический супервизор для определенных устройств на шине USB. Эти устройства имеют адреса и появляются и исчезают в течение срока службы системы.

Для каждого устройства мне нужен динамический ребенок для моего руководителя.

Эти дочерние элементы являются временными, поэтому, как только они падают или завершают работу, мы не перезапускаем их (потому что, вероятно, тогда они исчезнут).

У меня есть процесс, который сканирует USB-порт в определенное время и создает список всех адресов USB-устройств, которые я хочу обработать.

Я планирую вызывать supervisor:which_children/1 перед каждым сканированием, чтобы узнать, какие устройства присутствуют, но не имеют запущенных дочерних процессов.

Чтобы узнать, на каких адресах работают дочерние элементы, я планирую создать атомы идентификаторов для дочерней спецификации, которые содержат адреса (возможны только несколько адресов), например. 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 уже завершенных детей.

Поэтому было бы лучше, если бы потомки удалялись после их временного завершения.

Как-то все это кажется мне неэлегантным, поэтому я спрашиваю себя (и вас):

Как я могу решить это наиболее элегантно?

Не лучше ли вообще не использовать супервайзер в этой ситуации?


person Peer Stritzinger    schedule 12.03.2011    source источник


Ответы (2)


Моя интуиция/реакция коленного рефлекса такова: «Вам нужно использовать супервизора simple_one_for_one для них, чтобы их спецификация была удалена, когда она остановится. Если вам нужно захватить определенный процесс для связи, я бы использовал для этого приложение gproc (или таблицу ETS).

person I GIVE CRAP ANSWERS    schedule 12.03.2011
comment
проблема с simple_one_for_one заключается в том, что нелегко выяснить, какие адреса отсутствуют в процессе. Мне пришлось бы реализовать отдельный реестр адресов, который отслеживает процессы. Какой цели тогда служит супервизор simple_one_for_one? - person Peer Stritzinger; 13.03.2011
comment
gproc звучит действительно привлекательно для этого BTW - person Peer Stritzinger; 13.03.2011
comment
супервизор simple_one_for_one предназначен для подключения к процессам, поэтому, если какой-либо другой процесс умирает, вы можете изящно отключить USB-соединения. Это для уборки, не более того. - person I GIVE CRAP ANSWERS; 13.03.2011
comment
Я понимаю. Однако это не моя забота: для каждого USB-устройства, которым управляет ребенок, запускается полный набор связанных процессов. Если здесь что-то пойдет не так, дочерний процесс все равно будет завершен и перезапущен. Кроме того, происходит то, что новые устройства подключаются, а иногда устройства исчезают и появляются снова (довольно быстро). Я экспериментирую с обычным супервайзером one_for_one с детьми, добавленными и удаленными в процессе сканирования (исчезновение и повторное появление часто происходят по одному и тому же адресу и могут обрабатываться супервизором самостоятельно) - person Peer Stritzinger; 13.03.2011
comment
Кстати: адрес не нужен, чтобы захватить процесс для связи, просто чтобы запустить правильный обработчик USB (адреса выдаются операционной системой на лету и не имеют ничего общего с чем-либо полезным). У меня уже есть отдельный реестр для этого, управляемый серийными номерами устройств, когда я с ними разговариваю. - person Peer Stritzinger; 13.03.2011
comment
Я думаю, было бы целесообразно отделить поддержку одного процесса для каждого USB-устройства от того, как сопоставлять {VendorID,ProductID}, серийные номера устройств (которые могут быть не уникальными), классы устройств и т. д. для процессов и обратно. - person ndim; 14.03.2011

Мне кажется, что дети, которых вы хотите динамически добавить к своему руководителю, очень похожи друг на друга. Возможно, вам нужен simple-one-for-one руководитель. Эти супервизоры представляют собой «упрощенную версию супервизора one_for_one, где все дочерние процессы являются динамически добавляемыми экземплярами одного и того же процесса». У каждого дочернего элемента будут одни и те же дочерние спецификации, поэтому вам не нужно указывать их при вызове метода supervisor:add_child/2.

Кроме того, имейте в виду, что приведенная выше идея динамического создания атома (например, adr_12) может быть опасной. Атомы в системе Erlang ограничены (по умолчанию ~1000000). Подробности смотрите в документации.

person Roberto Aloi    schedule 12.03.2011
comment
На шине USB всего 127 возможных адресов, всегда используются только младшие адреса, поэтому создание атома не является проблемой. - person Peer Stritzinger; 13.03.2011
comment
Конечно. Я просто подумал, что было бы полезно упомянуть эту проблему - кто-то может посмотреть на этот вопрос и решить использовать тот же подход с гораздо большим количеством детей - - person Roberto Aloi; 13.03.2011
comment
См. также мой комментарий к ответу @IGCA. - person Peer Stritzinger; 13.03.2011