【问题标题】:Understanding the return value of spawn理解 spawn 的返回值
【发布时间】:2011-09-19 01:45:48
【问题描述】:

我刚开始使用 Erlang,在将 spawn/3 返回的 PID 应用于 process_info/1 方法时,可以帮助理解不同的结果。

给定这个导出a/0函数的简单代码,它只是调用b/0,它等待消息:

-module(tester).
-export([a/0]).

a() ->
    b().
b() ->
    receive {Pid, test} ->
        Pid ! alrighty_then
    end.

...请帮助我了解 shell 输出不同的原因:


示例 1:

这里,Pid 中的current_function 显示为tester:b/0

Pid = spawn(tester, a, []).

process_info( Pid ).

> [{current_function,{tester,b,0}},
    {initial_call,{tester,a,0}},
    ...

示例 2:

这里,process_info/1 中的current_function 显示为tester:a/0

process_info( spawn(tester, a, []) ).

> [{current_function,{tester,a,0}},
    {initial_call,{tester,a,0}},
    ...

示例 3:

这里,process_info/1current_function 显示为tester:a/0,但Pidcurrent_functiontester:b/0

process_info( Pid = spawn(tester, a, []) ).

> [{current_function,{tester,a,0}},
    {initial_call,{tester,a,0}},
    ...

process_info( Pid ).

> [{current_function,{tester,b,0}},
    {initial_call,{tester,a,0}},
    ...

我假设在调用 spawn/3 时在后台发生了一些异步代码,但是变量赋值和参数传递如何工作(尤其是在最后一个示例中)使得 Pid 获得一个值,而 process_info/1 获得另一个?

Erlang 中有什么特别的东西可以在这种情况下绑定变量赋值,但没有为参数传递提供这种绑定?


编辑:

如果我使用这样的函数:

TestFunc = fun( P ) -> P ! {self(), test}, flush() end.

TestFunc( spawn(tester,a,[]) ).

...消息从tester:b/0正确返回:

Shell got alrighty_then
ok

但是如果我使用这样的函数:

TestFunc2 = fun( P ) -> process_info( P ) end.

TestFunc2( spawn(tester,a,[]) ).

...process_info/1 仍然显示tester:a/0

[{current_function,{tester,a,0}},
 {initial_call,{tester,a,0}},
 ...

不知道该怎么做。也许我只需要接受它高于我的工资等级!

【问题讨论】:

    标签: erlang argument-passing variable-assignment spawn


    【解决方案1】:

    如果您查看 spawn 的文档,它会说它返回新创建的 Pid 并将新进程放入系统调度程序队列中。换句话说,进程开始了,但调用者继续执行。

    Erlang 与其他一些语言的不同之处在于您不必显式地让出控制权,而是依靠进程调度程序来确定何时执行哪个进程。在您分配给Pid 的情况下,调度程序有足够的时间切换到生成的进程,该进程随后调用b/0

    【讨论】:

    • 所以“系统调度程序”==“不要担心细节”。我可以处理。我确实首先阅读了文档,这就是最初让我开始思考这个问题的原因。我想知道为什么我生成a/0 却得到b/0 的PID。我的意思是这当然是理想的行为,但我无法理解它的机制。我猜 Erlang 只知道在那种情况下要返回哪个 PID。
    • Pid 没有改变——它“指向”一个正在运行的进程。在运行时,它执行不同的功能(在您的情况下是 A,然后是 B)。 current_function 仅向您显示该进程恰好在您调用 process_info/1 的那一刻正在执行的函数。如果您设法立即查看它,它将位于a/0,但如果您提供足够长的时间,它将位于b/0
    • 啊!!!我的想法是错误的(显然)。在我的脑海中,当你生成一个进程(通过引用spawn/3 中的一个函数)时,沿途调用的每个函数都会有它自己唯一的 PID 与之关联。但相反,该过程更广泛,并且可能包含许多函数的调用,并且 PID 只是对正在发生的整个“过程”的引用。如果这听起来是正确的(虽然说得很笨拙),那么我相信我理解它。
    【解决方案2】:

    这真的很简单。生成的进程的执行从调用 a() 开始,稍后不久将调用 b(),然后就坐在那里等待,直到它收到特定的消息。在您设法立即在 pid 上调用 process_info 的示例中,您在进程仍在执行 a() 时捕获它。在其他情况下,当涉及到一些延迟时,您会在它调用 b() 后捕获它。这有什么令人困惑的?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 2014-04-28
      相关资源
      最近更新 更多