Process 如何在Erlang中分叉/克隆进程

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. 有什么想法吗 编辑: 为了更好地解释我的观点,以下面的

如何在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.
有什么想法吗

编辑:

为了更好地解释我的观点,以下面的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()])
也应该由子进程执行,对吗?但是,如果您以这种方式
生成
,控制流将被分离。请接受这个答案,因为它对我帮助最大。你知道是否有任何方法可以克隆控制流以及状态(数据)?@肖佳,我不知道这是否是你真正想要的:但是,据我所知,流控制是基于进程的当前状态。所以,在分叉具有几乎相同状态的子进程之后,您可能会向其传递一条消息,其中告诉他做一些事情(或者做与父进程相同的事情)。所以它模拟了一种流控制的克隆。从概念上来说,这是可以的。但我正在尝试编写一个第三方实用程序,它实际上可以进行分叉,同时向用户隐藏细节。接受这个答案,因为它对我帮助最大。你知道是否有任何方法可以克隆控制流以及状态(数据)?@肖佳,我不知道这是否是你真正想要的:但是,据我所知,流控制是基于进程的当前状态。所以,在分叉具有几乎相同状态的子进程之后,您可能会向其传递一条消息,其中告诉他做一些事情(或者做与父进程相同的事情)。所以它模拟了一种流控制的克隆。从概念上来说,这是可以的。但我正在尝试编写一个第三方实用程序,它实际上可以进行分叉,同时对用户隐藏细节。