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)
然后,该过程与原因终止Reason
了exit/1
或{Reason,Stack}
换了别人。
一个进程也可以被终止,如果它接收到另一个退出原因的退出信号normal
,参见Error Handling
。
12.5信息发送
进程通过发送和接收消息进行通信。通过使用send operator !
和通过呼叫接收消息receive
。
消息发送是异步且安全的,只要收件人存在,邮件就会保证最终到达收件人。
12.6链接
两个进程可以相互关联
。两个过程之间的链接Pid1
,并Pid2
通过创建Pid1
调用BIF link(Pid2)
(或相反)。还有一些spawn_link
BIF,在一次操作中产生并链接到一个进程。
链接是双向的,两个进程之间只能有一个链接。重复的呼叫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()