3.5.6进程连接与监视者
3.5.6.1进程连接:
将一组进程组合在一起,其中任意一个进程错误死掉,其它进程都被连带停掉
进程连接是对称的,A连接到B,则B自动也连接到A
eg: 在A进程中,执行
B = spawn_link(fun() -> ... end).
则A和B连接了,当B发生异常死掉时,会发送退出信号{'EXIT',B,Why}给A进程,当Why不为normal时,则A也会死掉。
例外,当接收进程是个系统进程时,即使收到退出信号,也不会退出(除非发送exit(Pid, kill))
process_flag(trap_exit, true). 变为系统进程
eg: 系统进程处理其它进程错误的典型代码
start() ->spawn(fun go/0).
go() ->
process_flag(trap_exit, true),
loop().
loop() ->
receive
{'EXIT',P,Why} ->
.... handle the error
end.
主动发送错误消息:
exit(Pid, Why). 发送方伪装死亡,接收方Pid将收到退出信号
exit(Pid, kill).发送"不可阻挡的退出信号",包括系统进程在内的进程都将退出
3.5.6.2进程监视者:
非对称的连接,一个进程可以监视其它进程,一个多用在C/S系统中,Server死掉时,可以杀掉所有client,而某个client死掉时,不能杀死server
eg: 在进程A中设置监视者, A和B都不必是系统进程
Ref = erlang:monitor(process, B).
当B死掉时,B向A发送消息
{'DOWN', Ref, process, B, Why}
3.6分布式编程
两个原语:
spawn(Node, Fun):在远端节点Node上,生成函数是Fun的进程
monitor(Node):用来监视整个节点的行为,而不仅仅是某个进程
3.7端口ports
进程与外界通信的机制:每个端口有个关联的"控制进程",只有此进程才能往此端口发送消息,此端口收到的消息都发送到此进程。
open_port/2创建,一般创建进程是此端口的控制进程,也可以改变
eg:端口发送消息
Port ! {Pid, Command} //端口Port发送给Pid,执行Command命令,有三种形式
(1)Port ! {Pid, {command, Data}}.发送命令command,传递数据Data,
(2)Port ! {Pid, close}. 关闭端口,端口会向控制进程回复 {Port, closes}消息
(3)Port ! {connect, Pid1}.将端口的控制进程改为Pid1,端口给原控制进程发送{Port, connected}消息,此后的消息将发送给Pid1
3.8动态代码
可以动态支持版本更新(最多两个版本同时运行)。更新版本后,旧程序有两种方式:可以运行新程序,可以运行旧程序
(1)动态替换为新版本
当代码是通过全修饰名被调用的,即ModuleName:FuncName调用,则更新后,会调用新版本
-module(m)
...
loop(Data, F) ->
receive
{From, Q} ->
{Reply, Data1} = F(Q,Data),
m:loop(data1,F)
end.
(2)仍然调用旧版本
-module(m)
...
loop(Data, F) ->
receive
{From, Q} ->
{Reply, Data1} = F(Q,Data),
loop(data1,F)
end.
(3)最多支持两个版本,如果再有版本更新,则仍执行最旧的版本的进程将被杀死
3.9类型符号
相当于类型定义:type定义函数,deftype定义类型
原始类型包括
int(), atom(), pid(), ref()引用类型,float(),port(),bin()二进制类型
可以自定义类型
+deftype name1() = name2() = ... = Type.
+deftype bool() = true | false.
+deftype weekday() = monday|tuesday|wednesday|thursday|friday.
+deftype weekend() = saturday() | sunday().
+deftype day() = weekday()|weekend().
+deftype string() = [int()].
+deftype day2() = number() = int().
+deftype town() = street() = string().
自定义函数类型
+type functionName(T1,T2,...Tn) ->T.
+type factorial(int()) -> int().
+type day2int(day()) -> int().
+type address(person()) -> {town(), street(),number()}.
+type fun(T1,T2...Tn) -> T end. 匿名函数