首先我正在学习Erlang。根本不是专家。在使用ET进行一些示例时,我遇到了我不了解的东西(即使在搜索之后)。
我有一个用
创建公共ET的过程TableID = ets:new(tablename, [public])}
i然后将表格传递给其他过程。当我这样做时,运行模块会形成外壳,一切都可以。当我使用erl -noshell -s ...甚至没有-noshell选项的完全相同的模块时,它会失败。我不断出现错误:badarg好像不存在表。ID正确通过,但桌子实际上表现为私人!
从外壳或没有?
的交互模块之间有区别谢谢
我正在添加我用来尝试调试问题的代码的示例。由于它是一个较大的软件(并且基本上被剥离到骨头以找到问题),因此可能很难理解。
-record(loop_state, {
commands
}).
start() ->
LoopState = #loop_state{commands = ets:new(commands, [public])},
tcpserver_otp_backend:start(?MODULE, 7000, {?MODULE, loop}, LoopState).
loop(Socket, LoopState = #loop_state{commands = Commands}) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
% the call below fails, no error generated, AND only in non interactive shell
A = newCommand(Commands, Data),
gen_tcp:send(Socket, A),
loop(Socket, LoopState);
{error, closed} ->
ok
end.
newCommand(CommandTableId, Command) ->
case ets:lookup(CommandTableId,Command) of
[] ->
_A = ets:insert(CommandTableId, {Command, 1}),
<<1, "new", "1">>; % used for testing
_ ->
<<1, "old", "1">> % used for testing
end.
当我删除"犯罪命令" ETS:查找时,所有这些都可以作为int互动壳。
问题似乎是您在start()函数中创建了ETS表。ETS表有一个所有者(默认情况下,创建过程),当所有者死亡时,该表被删除。当您通过将-s传递到ERL从命令行运行启动/0函数时,该所有者进程将是ERLANG内核中的某个内部进程,它是处理启动序列的一部分。不管您是否通过-noshell,该过程可能是短暂的,并且在查找功能有时间执行之前会死亡,因此当查找最终发生时,该表不再存在。
创建ETS表的合适位置将在您启动的Gen_Server的init()回调函数中。如果应该是通过多个进程访问的公共est表,那么您可能需要创建一个单独的服务器进程,其任务是拥有该表。