0

Erlang R16B03-1 (erts-5.10.4)在 OS X 10.9.2 上运行。Erlang 是使用 brew 安装的。

我正在尝试运行 gen_server 模块。

-module(logger).
-author("evangelosp").

-behaviour(gen_server).

%% API
-export([start/0, stop/0, log/2]).

%% gen_server callbacks
-export([init/1,
  handle_call/3,
  handle_cast/2,
  handle_info/2,
  terminate/2,
  code_change/3]).

-define(SERVER, ?MODULE).

%%%===================================================================
%%% API
%%%===================================================================

start() -> gen_server:start_link({global, ?SERVER}, ?MODULE, [], []).

stop() -> gen_server:call(?MODULE, stop).

log(_Level, _MSG) -> gen_server:call(?MODULE, {add, {_Level, _MSG}}).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

init([]) -> {ok, ets:new(?MODULE, [])}.

handle_call(_Request, _From, Table) -> {reply, {ok, ["Mplah!", _Request, _From, Table]}, Table}.

handle_cast(_Request, State) -> {noreply, State}.

handle_info(_Info, State) -> {noreply, State}.

terminate(_Reason, _State) -> ok.

code_change(_OldVsn, State, _Extra) -> {ok, State}.

在我正在运行的 erlang shell 中:

Eshell V5.10.4  (abort with ^G)
1> c(logger).
{ok,logger}
2> logger:start().
{ok,<0.40.0>}
3> logger:log(info, "Hello World").
** exception exit: {noproc,{gen_server,call,
                                       [logger,{add,{info,"Hello World"}}]}}
     in function  gen_server:call/2 (gen_server.erl, line 180)

我无法摆脱那个例外。通过查找异常消息,我实际上并没有找到任何有用的资源,但这没有太大帮助。

干杯。

4

2 回答 2

2

在您的代码start() -> gen_server:start_link({global, ?SERVER}, ?MODULE, [], []).中,您使用{global, ?SERVER}这意味着:

如果 ServerName={global,GlobalName} 使用 global:register_name/2 将 gen_server 全局注册为 GlobalName。

所以当你向服务器发送消息时,你应该写log(_Level, _MSG) -> gen_server:call({global, ?MODULE}, {add, {_Level, _MSG}}).. 请参阅 erlang 文档:

call(ServerRef, Request, Timeout) -> 回复类型:ServerRef = Name | {名称,节点} | {全球,全球名称} | ServerRef 可以是:

名称,如果 gen_server 是本地注册的,

{global,GlobalName},如果 gen_server 是全局注册的。

于 2014-06-09T01:02:18.040 回答
1

您的服务器未注册,因此只能通过其 pid 访问它。但是接口函数使用隐式宏 ?MODULE(在编译时被 logger 替换)来访问它。

您需要更改界面功能,或者在启动功能中注册服务器:

start() ->
  {ok,Pid} = gen_server:start_link({global, ?SERVER}, ?MODULE, [], []),
  register(?MODULE,Pid).

[编辑]感谢Evalon,我在答案中进行了更正:o)

于 2014-06-08T11:06:25.950 回答