在线文档教程
Erlang 20

12.流程 | 12. Processes

12 过程

12.1过程

Erlang专为大规模并发而设计。Erlang进程是轻量级的(动态增长和缩减),占用内存很小,创建和终止的速度很快,而且调度开销很低。

12.2进程创建

通过调用创建一个进程spawn

spawn(Module, Name, Args) -> pid() Module = Name = atom() Args = [Arg1,...,ArgN] ArgI = term()

spawn创建一个新进程并返回PID。

新进程Module:Name(Arg1,...,ArgN)在参数是(可能为空)Args参数列表的元素的位置开始执行。

例如spawn,还有一些其他的BIF用于spawn/4在另一个节点产生一个进程。

12.3注册过程

除了通过使用其pid来处理进程之外,还有用于在名称下注册进程的BIF。该名称必须是原子,并且如果该过程终止,它将自动取消注册:

BIF描述
register(Name, Pid)将名称Name,一个原子与进程Pid关联。
registered()返回使用register / 2注册的名称列表。
whereis(Name)返回在Name下注册的pid,或者未定义的名称未注册。

12.4进程终止

当进程终止时,它总是以退出原因结束。原因可以是任何术语。

如果退出原因是原子,则称进程正常终止normal。没有更多代码执行的进程正常终止。

{Reason,Stack}发生运行时错误时,进程终止并显示退出原因。看Exit Reasons

进程可以通过调用以下BIF之一来终止它自己:

  • exit(Reason)

  • erlang:error(Reason)

  • erlang:error(Reason, Args)

然后,该过程与原因终止Reasonexit/1{Reason,Stack}换了别人。

一个进程也可以被终止,如果它接收到另一个退出原因的退出信号normal,参见Error Handling

12.5信息发送

进程通过发送和接收消息进行通信。通过使用send operator !和通过呼叫接收消息receive

消息发送是异步且安全的,只要收件人存在,邮件就会保证最终到达收件人。

12.6链接

两个进程可以相互关联。两个过程之间的链接Pid1,并Pid2通过创建Pid1调用BIF link(Pid2)(或相反)。还有一些spawn_linkBIF,在一次操作中产生并链接到一个进程。

链接是双向的,两个进程之间只能有一个链接。重复的呼叫link(Pid)不起作用。

通过调用BIF可以删除链接unlink(Pid)

链接用于监视其他进程的行为,请参阅Error Handling

12.7错误处理

Erlang具有用于进程间错误处理的内置功能。终止进程向所有链接的进程发出退出信号,这些进程也可以终止,或以某种方式处理退出。此功能可用于构建分层程序结构,其中某些进程正在监督其他进程,例如,如果它们异常终止,则会重新启动它们。

请参阅OTP Design Principles有关使用此功能的OTP监督树的更多信息。

发出出口信号

当一个进程终止时,它终止于退出原因,如下所述Process Termination。这个退出原因在退出信号中发送到所有链接的进程。

一个进程也可以调用该函数exit(Pid,Reason)。这导致退出信号Reason发出退出原因Pid,但不影响调用过程。

接收出口信号

当一个进程接收到一个退出信号而不是一个退出信号时的默认行为normal是终止,并以相同的退出原因发出退出信号给它的链接进程。有理由的退出信号normal被忽略。

可以将进程设置为通过调用:

process_flag(trap_exit, true)

当进程陷入退出时,当收到退出信号时它不会终止。相反,信号被转换成一条消息{'EXIT',FromPid,Reason},它被放入进程的邮箱中,就像常规消息一样。

上述例外情况是,如果退出原因是kill,即是否exit(Pid,kill)已被调用。无条件终止该过程,而不管它是否陷入退出信号。

12.8显示器

链接的替代方法是监视器。一个进程Pid1可以Pid2通过调用BIF 来创建一个监视器erlang:monitor(process, Pid2)。该函数返回一个引用Ref

如果Pid2以退出原因结束,Reason则发送'DOWN'消息至Pid1

{'DOWN', Ref, process, Pid2, Reason}

如果Pid2不存在,则立即发送'DOWN'消息并将其Reason设置为noproc

监视器是单向的。重复调用erlang:monitor(process, Pid)创建多个独立的监视器,每个监视器Pid终止时发送一个'DOWN'消息。

监视器可以通过调用来删除erlang:demonitor(Ref)

可以为注册名称的进程创建监视器,也可以在其他节点上创建监视器。

12.9 进程字典

每个进程都有自己的进程字典,通过调用以下BIF进行访问:

put(Key, Value) get(Key) get() get_keys(Value) erase(Key) erase()