进程间通信
在Erlang中进行进程间通信的唯一方法就是消息传递。一个消息通过原语!(send)发送给另一个进程:
Pid ! Message
send是一个会对其参数进行求值的原语。它的返回值是发送的消息。
原语receive被用于接收消息。它的语法如下:
receive
Message1 [when Guard1] ->
Actions1 ;
Message2 [when Guard2] ->
Actions2 ;
end.
每个进程都有一个邮箱,所有发送到该进程的消息都被按照它们到达的顺序依次存储在邮箱里。
当找到一个匹配的消息并且对应的保护式(Guard)满足的时候,这个消息就被选中,并从邮箱中删除,同时对应的ActionsN会被执行。receive会返回ActionosN中最后一个表达式求值的结果。就如同Erlang里其他形式的模式匹配一样,消息模式中未绑定(unbound)量会被绑定(bound)被receive选中的消息会按照原来的顺序继续留在邮箱中,用于下一次recieve的匹配。调用receive的进程会一直阻塞,直到有匹配的消息为止。
消息接收的顺序
当receive尝试寻找一个匹配的消息的时候,它会依次对邮箱中的每一个消息尝试用给定的每个模式去进行匹配。
只接收来自某个特定进程的消息
有时候我们会只希望接收来自某一个特定进程的消息。要实现这个机制,消息发送者必须显式地在消息中包含自己的进程标识符:
Pid | {self(),Message}
BIF self()返回当前进程的标识符。这样的消息可以通过如下方式来接收:
receive
{Pid, Message} ->
Actions;
end.
节点间通信
Erlang内置了相关语意允许程序跨多节点执行:多个进程可以透明地在其他节点上分裂出进程,并相互通过消息传递来通信。分布式节点可以位于同一个物理机上,也可以分布在不同主机上。
命名与通信
短命名:
erl -sname node
节点使用主机名(hostname)作为在本地网络的表示。
长命名:
erl -name node
使用一个全限定的域名或IP地址。
在一个分布式系统内,所有节点必须使用同一种命名模式,例如全是短命名或全是长命名。
节点间连接和可见性
为了能够互相通信,所有节点必须共享一个私密的cookie值。相同cookie值的节点会进行全相连的网状连接。
但如果在启动节点时带上-hidden标志,节点就不会自动和任何节点连接。可以使用net_kernel模块进行细粒度的控制。
隐藏式节点有多重用途,比如用于运维或者作为桥连接不同的节点集群。
节点连接
A节点连接B节点,如果在同一机器上,只需要进程间通讯就可以找到节点。
不在同一台机器上,通过epmd来搞定(链接:epmd学习笔记)。