在初始化Erlang管理程序进程时添加gen_event处理程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在初始化Erlang管理程序进程时添加gen_event处理程序相关的知识,希望对你有一定的参考价值。

我正在学习Erlang,并且正在设法找到答案并相对有效地解决大多数问题的解决方案,但是花了不可接受的时间来解决这个问题:

将处理程序添加到由主管进程启动的gen_event模块的正确方法是什么?到目前为止,在我的探索中,我已经能够设置进程,gen_servers,supervisor(启动gen_servers)和gen_event模块,但我试图为gen_event添加处理程序的所有内容都会导致我的主管进程崩溃 - 有时甚至是我的壳!!

主管模块:

-module(sup).
-behaviour(supervisor).

%% API
-export([start_link/0, init/1]).
-export([stop/0]).

start_link() ->
  supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init(_) ->
  EventServerSpec = #{
    id => osc_event_server,
    start => {gen_event, start_link, [{local, osc_server}]},
    modules => dynamic
  },
  ChildSpecList = [EventServerSpec, child(frequency), child(bkpt_server)],
  SupFlags = #{strategy => rest_for_one,
    intensity => 2, period => 3600},
  {ok, {SupFlags, ChildSpecList}}.

child(Module) ->
  #{id => Module,
    start => {Module, start_link, []},
    restart => permanent,
    shutdown => 2000,
    type => worker,
    modules => [Module]}.

...以及来自gen_event模块的一些零碎件,osc_event_server(希望是相关的!)

...
init([]) ->
  {ok, Socket} = gen_udp:open(8980, [binary, {active, false}]),
  {ok, #{socket => Socket, target_port => get_target_port()}}.

...
handle_event({send_osc, Path, Data}, State) ->
  TargetPort = maps:get(target_port, State),
  Socket = maps:get(socket, State),
  sendMessage(Socket, TargetPort, Path, Data),
  {ok, State};
...

尽管我对gen_event行为了解不多,但我对运行包含这些片段的代码的结果并不感到惊讶:

  • 它发射没有崩溃
  • 它启动了gen_event并为它生成了一个可引用的Pid,但从未命中'osc_event_server'的init
  • 没有附加到gen_event的实际事件处理程序。 “which_handlers”和尝试发送消息都证实了这一点。

我要加入的两件事:

  1. 将特定事件处理程序(例如,“send_osc”)附加到我的gen_event进程...希望从管理程序代码中
  2. 将初始化参数传递给osc_event_server模块;我希望至少能够为UDP服务器指定端口(而不是硬连线“8980”)并提供我希望我的进程与之通信的远程UDP服务器的IP +端口。

非常感谢。随意批评你看到的任何东西......例如,我的整个方法:)尽管我已经明白了Erlang,但我确定,与我误解的Erlang数量相比,这没什么。

答案

您应该将gen_event进程视为节点上存在的一种服务。通常你会给它一个名字,并使用该名称与它交谈。在你这样做之前,这是一段独立的代码。

这意味着如果你想添加处理程序,假设你不能在管理程序中运行任意代码来执行它,最简单的方法是让你的主管在gen_event进程准备好后生成一个兄弟进程。

将新兄弟标记为transienttemporary,让它成为一个小gen_serversupervisor_bridge工人,并给它命名和gen_event的处理程序。小工人应该添加处理程序。然后它可以通过normal原因关闭,或者如果需要,可以监督处理程序,以防它们崩溃以重新添加它们。

以上是关于在初始化Erlang管理程序进程时添加gen_event处理程序的主要内容,如果未能解决你的问题,请参考以下文章

Erlang模块supervisor翻译

在 Erlang 中实现图灵机

Erlang:守护进程“init.d”脚本无法启动

Erlang:supervisor(3),添加子进程

Erlang 更改 VM 进程的初始大小。调整 Erlang 虚拟机

Erlang 源码分析之 Gen_Server