Process 如何在Erlang中分叉/克隆进程
如何在Erlang中分叉/克隆进程,如Unix中的Process 如何在Erlang中分叉/克隆进程,process,erlang,fork,Process,Erlang,Fork,如何在Erlang中分叉/克隆进程,如Unix中的fork 我找了很多,但什么也没找到 可能用法如下所示: case fork() of {parent, Pid} -> in_parent_process_now(); {child, Pid} -> in_child_process_now(); {error, Msg} -> report_fork_error(Msg) end. 有什么想法吗 编辑: 为了更好地解释我的观点,以下面的
fork
我找了很多,但什么也没找到
可能用法如下所示:
case fork() of
{parent, Pid} ->
in_parent_process_now();
{child, Pid} ->
in_child_process_now();
{error, Msg} ->
report_fork_error(Msg)
end.
有什么想法吗
编辑:
为了更好地解释我的观点,以下面的C代码为例:
f();
fork();
g();
这里忽略了fork()
的返回值,因此父进程和子进程的后续步骤是相同的,即执行g()
我可以在Erlang中实现这一点吗 (这个问题很难回答。)
Erlang没有“fork”操作。它有一个spawn
操作,但是:
parent_process() ->
will_be_executed_by_parent_process(),
spawn(fun() -> will_be_executed_by_child_process() end),
will_also_be_executed_by_parent_process().
。。。其中函数名显示它们将在什么上下文中执行。请注意,传递给子进程的任何数据都将复制到新进程的堆中。(此问题已解决。)
Erlang没有“fork”操作。它有一个spawn
操作,但是:
parent_process() ->
will_be_executed_by_parent_process(),
spawn(fun() -> will_be_executed_by_child_process() end),
will_also_be_executed_by_parent_process().
。。。其中函数名显示它们将在什么上下文中执行。请注意,传递给子进程的任何数据都将复制到新进程的堆中。Erlang中没有fork。但是你可以在spawn/1、spawn/2、spawn/3、spawn/4(参见spawn_链接)中使用一个,它们是erlang的BIF 例如:
-module(mymodule).
-export([parent_fun/0]).
parent_fun() ->
io:format("this is the parent with pid: ~p~n", [self()]),
spawn(fun() -> child_fun() end),
io:format("still in parent process: ~p~n", [self()]).
child_fun() ->
io:format("this is child process with pid: ~p~n", [self()]).
在erlang shell中执行为:
mymodule:parent_fun().
请注意,父进程和子进程具有不同的PID
我强烈建议您阅读:Erlang中没有fork。但是你可以在spawn/1、spawn/2、spawn/3、spawn/4(参见spawn_链接)中使用一个,它们是erlang的BIF 例如:
-module(mymodule).
-export([parent_fun/0]).
parent_fun() ->
io:format("this is the parent with pid: ~p~n", [self()]),
spawn(fun() -> child_fun() end),
io:format("still in parent process: ~p~n", [self()]).
child_fun() ->
io:format("this is child process with pid: ~p~n", [self()]).
在erlang shell中执行为:
mymodule:parent_fun().
请注意,父进程和子进程具有不同的PID
我强烈建议您阅读:如您所知,在erlang中实现流程有一种通用模式:
loop( State ) ->
receive
Message ->
NewState = process( Message, State ),
loop( NewState )
end.
在每个时间量中,进程都有一个状态
。所以,如果您想从当前进程“分叉”某些进程,您必须为其传递特定的消息。进程必须识别该消息,并在生成的进程中生成新进程及其当前状态的副本
我创建了一个示例来说明上面的文本:
-module( test ).
-export( [ fork/1, get_state/1, change_state/2 ] ).
-export( [ loop/1 ] ).
loop( State ) ->
receive
{ fork, Sender } ->
%%
%% if you want to link with child process
%% call spawn_link instead of spawn
%%
ClonePid = spawn( ?MODULE, loop, [ State ] ),
responseTo( Sender, ClonePid ),
loop( State );
{ get_state, Sender } ->
responseTo( Sender, { curr_state, State } ),
loop( State );
{ change_state, Data, Sender } ->
{ Response, NewState } = processData( Data, State ),
responseTo( Sender, Response ),
loop( NewState )
end.
fork( Pid ) ->
Ref = make_ref(),
Pid ! { fork, { Ref, self() } },
get_response( Ref ).
get_state( Pid ) ->
Ref = make_ref(),
Pid ! { get_state, { Ref, self() } },
get_response( Ref ).
change_state( Pid, Data ) ->
Ref = make_ref(),
Pid ! { change_state, Data, { Ref, self() } },
get_response( Ref ).
get_response( Ref ) ->
receive
{ Ref, Message } -> Message
end.
responseTo( { Ref, Pid }, Mes ) ->
Pid ! { Ref, Mes }.
processData( Data, State ) ->
%%
%% here comes logic of processing data
%% and changing process state
%%
NewState = Data,
Response = { { old_state, State }, { new_state, NewState } },
{ Response, NewState }.
让我们在erlang shell中测试它:
1> c(test).
{ok,test}
使用初始状态创建父进程first\u state
2> ParentPid = spawn( test, loop, [ first_state ] ).
<0.38.0>
3> test:get_state( ParentPid ).
{curr_state,first_state}
4>
从父进程派生新进程:
5> ChildPid = test:fork( ParentPid ).
<0.42.0>
6> test:get_state( ChildPid ).
{curr_state,second_state}
正如您所知,在erlang中实现流程有一种通用模式:
loop( State ) ->
receive
Message ->
NewState = process( Message, State ),
loop( NewState )
end.
在每个时间量中,进程都有一个状态
。所以,如果您想从当前进程“分叉”某些进程,您必须为其传递特定的消息。进程必须识别该消息,并在生成的进程中生成新进程及其当前状态的副本
我创建了一个示例来说明上面的文本:
-module( test ).
-export( [ fork/1, get_state/1, change_state/2 ] ).
-export( [ loop/1 ] ).
loop( State ) ->
receive
{ fork, Sender } ->
%%
%% if you want to link with child process
%% call spawn_link instead of spawn
%%
ClonePid = spawn( ?MODULE, loop, [ State ] ),
responseTo( Sender, ClonePid ),
loop( State );
{ get_state, Sender } ->
responseTo( Sender, { curr_state, State } ),
loop( State );
{ change_state, Data, Sender } ->
{ Response, NewState } = processData( Data, State ),
responseTo( Sender, Response ),
loop( NewState )
end.
fork( Pid ) ->
Ref = make_ref(),
Pid ! { fork, { Ref, self() } },
get_response( Ref ).
get_state( Pid ) ->
Ref = make_ref(),
Pid ! { get_state, { Ref, self() } },
get_response( Ref ).
change_state( Pid, Data ) ->
Ref = make_ref(),
Pid ! { change_state, Data, { Ref, self() } },
get_response( Ref ).
get_response( Ref ) ->
receive
{ Ref, Message } -> Message
end.
responseTo( { Ref, Pid }, Mes ) ->
Pid ! { Ref, Mes }.
processData( Data, State ) ->
%%
%% here comes logic of processing data
%% and changing process state
%%
NewState = Data,
Response = { { old_state, State }, { new_state, NewState } },
{ Response, NewState }.
让我们在erlang shell中测试它:
1> c(test).
{ok,test}
使用初始状态创建父进程first\u state
2> ParentPid = spawn( test, loop, [ first_state ] ).
<0.38.0>
3> test:get_state( ParentPid ).
{curr_state,first_state}
4>
从父进程派生新进程:
5> ChildPid = test:fork( ParentPid ).
<0.42.0>
6> test:get_state( ChildPid ).
{curr_state,second_state}
我认为这与Unix
fork
不同。如果您认为产卵< /code >作为<代码>叉
(我知道它们是不同的,只是说代码中的位置),<代码> WelyalSooBeExpRudEdTyByPrEntApdioType()/<代码>,由UNIX <代码> ORIX 的语义,也应该由子进程执行。我想这与UNIX <代码> Fooe不同。如果你认为<代码>产卵< /code >作为<代码>叉(我知道它们是不同的,只是说代码中的位置),<代码> WielasalSoBeExpReTueTyByPARTRONGROUP()/<代码>,由UNIX <代码> For < /code >的语义,也应该由子进程执行。code>io:format(“仍在父进程中:~p~n”,[self()])也应该由子进程执行,对吗?但是如果你以这种方式spawn
,控制流是分开的。这个问题与@aronisstav的答案相同io:format(“仍在父进程中:~p~n”,[self()])
也应该由子进程执行,对吗?但是,如果您以这种方式生成
,控制流将被分离。请接受这个答案,因为它对我帮助最大。你知道是否有任何方法可以克隆控制流以及状态(数据)?@肖佳,我不知道这是否是你真正想要的:但是,据我所知,流控制是基于进程的当前状态。所以,在分叉具有几乎相同状态的子进程之后,您可能会向其传递一条消息,其中告诉他做一些事情(或者做与父进程相同的事情)。所以它模拟了一种流控制的克隆。从概念上来说,这是可以的。但我正在尝试编写一个第三方实用程序,它实际上可以进行分叉,同时向用户隐藏细节。接受这个答案,因为它对我帮助最大。你知道是否有任何方法可以克隆控制流以及状态(数据)?@肖佳,我不知道这是否是你真正想要的:但是,据我所知,流控制是基于进程的当前状态。所以,在分叉具有几乎相同状态的子进程之后,您可能会向其传递一条消息,其中告诉他做一些事情(或者做与父进程相同的事情)。所以它模拟了一种流控制的克隆。从概念上来说,这是可以的。但我正在尝试编写一个第三方实用程序,它实际上可以进行分叉,同时对用户隐藏细节。