【问题标题】:no_proc exception from gen_server来自 gen_server 的 no_proc 异常
【发布时间】:2014-04-29 20:22:42
【问题描述】:

执行以下代码时,gen_server 引发异常

    -module(drop).

    -behaviour(gen_server).

    -export([start_link/0]).

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

   -define(SERVER, ?MODULE).

   -record(state, {count}).

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

    init([]) ->
         {ok, #state{count=0}}.

    handle_call(_Request, _From, State) ->
      Distance = _Request,
      Reply = {ok, fall_velocity(Distance)},
      NewState=#state{ count= State#state.count+1},
      {reply, Reply, NewState}.

    handle_cast(_Msg, State) ->
      io:format("so far, calculated ~w velocities.~n", [State#state.count]),
      {noreply, State}.

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

    terminate(_Reason, _State) ->
        ok.  

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

    fall_velocity(Distance) -> math:sqrt(2 * 9.8 * Distance).   

输出:

1> gen_server:call(drop, 60).
** exception exit: {noproc,{gen_server,call,[drop,60]}}
in function  gen_server:call/2 (gen_server.erl, line 180).

上面的代码有什么问题?编译drop模块后需要编译gen_server模块吗?

【问题讨论】:

  • 请回复我,我是 Erlang 语言的初学者,每次重复出现相同问题时,我们将不胜感激

标签: erlang gen-server


【解决方案1】:

no_proc -- 意思是'没有进程' -- 你还没有启动你的服务器。

Gen_server 是 OTP 架构的一部分。这意味着您需要编写启动主管的应用程序来启动您的放置服务器。

然后你可以使用 gen_server:call 调用它

如果你只需要函数来计算速度,你实际上不需要OTP,你可以在模块中导出并调用一个函数..那种

-module(drop).
-export([fall_velocity/1]).
 .....

然后调用它

drop:fall_velocity(60).

BTW gen_server 模块已经在 erlang 库中编译。

【讨论】:

    【解决方案2】:

    您正在测试的代码运行良好。正如已经说过的,您需要启动 gen_server。这是这样做的方法,然后提出一些要求:

    1> c(drop).
    {ok,drop}
    2> S = spawn(drop,start_link,[]).
    <0.40.0>
    3> registered().
    [rex,net_sup,inet_db,kernel_sup,global_name_server,
     code_server,file_server_2,init,kernel_safe_sup,
     application_controller,user,error_logger,user_drv,
     standard_error,global_group,standard_error_sup,drop,auth,
     erl_epmd,net_kernel,erl_prim_loader]
    4> gen_server:call(drop,25).     
    {ok,22.135943621178658}
    5> gen_server:call(drop,13).
    {ok,15.962455951387932}
    6> gen_server:call(drop,20).
    {ok,19.79898987322333}
    7> gen_server:cast(drop,what).
    so far, calculated 3 velocities.
    ok
    

    命令 1 编译模块。 gen_server 无需编译,在 Erlang 库中已经完成。

    命令 2 启动 gen_server,一般在 drop 之类的模块中,添加一些接口函数来隐藏此调用,例如 start() -&gt; spawn(?MODULE,start_link,[]).,这样你就可以通过简单的调用 drop:start() 来启动服务器

    命令 3 显示新进程已注册,名称为 drop。

    命令 4,5 和 6 要求进行速度评估。至于开始,用法是有一个接口函数,比如velocity(N) -&gt; gen_server:call(?MODULE,N),所以你可以简单地call drop:velocity(25) 用法也是“装饰”消息,这样你以后可以有更多的功能

    命令 7 使用消息转换来获取到目前为止评估的速度数。关于界面和装饰的相同评论。这是一个更符合使用的版本:

    -module(drop).
    
    -behaviour(gen_server).
    
    %% interfaces
    -export([start_link/0,velocity/1,so_far/0]).
    
    -export([init/1,
    handle_call/3,
    handle_cast/2,
    handle_info/2,
    terminate/2,
    code_change/3]).
    
    -define(SERVER, ?MODULE).
    
    -record(state, {count}).
    
    %% interfaces
    
    start_link() -> 
        spawn (gen_server,start_link,[{local, ?SERVER}, ?MODULE, [], []]).
    
    velocity(N) ->
      gen_server:call(?MODULE,{get_velocity,N}).
    
    so_far() ->
      gen_server:cast(?MODULE,so_far). 
    
    %% call back
    
    init([]) ->
       {ok, #state{count=0}}.
    
    handle_call({get_velocity,Distance}, _From, State) ->
      Reply = {ok, fall_velocity(Distance)},
      NewState=#state{ count= State#state.count+1},
      {reply, Reply, NewState};
    
    handle_call(Request, _From, State) ->
      Reply = io:format("unknown request ~p~n",[Request]),
      {reply, Reply, State}.
    
    handle_cast(so_far, State) ->
      io:format("so far, calculated ~w velocities.~n", [State#state.count]),
      {noreply, State};
    
    handle_cast(Msg, State) ->
      io:format("unknown request ~p~n", [Msg]),
      {noreply, State}.
    
    handle_info(_Info, State) ->
      {noreply, State}.
    
    terminate(_Reason, _State) ->
      ok.  
    
    code_change(_OldVsn, State, _Extra) ->
      {ok, State}.
    
    fall_velocity(Distance) -> math:sqrt(2 * 9.8 * Distance).   
    

    现在命令看起来更简单了:

    12> drop:start_link().
    <0.60.0>
    13> drop:velocity(25).
    {ok,22.135943621178658}
    14> drop:velocity(20).
    {ok,19.79898987322333}
    15> drop:velocity(13).
    {ok,15.962455951387932}
    16> drop:so_far().    
    so far, calculated 3 velocities.
    ok
    

    【讨论】:

      【解决方案3】:

      您需要先启动服务器,然后才能通过gen_server:call/2 与其交互。

      drop:start_link().
      

      【讨论】:

        猜你喜欢
        • 2015-11-05
        • 1970-01-01
        • 2017-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多