在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 區(qū)塊鏈/ 錯(cuò)誤處理
注冊進(jìn)程名稱
錯(cuò)誤處理
完整示例
分布式編程
消息傳遞
if 與 case
健壯性
映射 (Map)
高階函數(shù) (Fun)
輸出至終端
更多關(guān)于列表的內(nèi)容
內(nèi)置函數(shù) (BIF)
模塊與函數(shù)
將大程序分在多個(gè)文件中
匹配、Guards 與變量的作用域
超時(shí)
列表
完整示例
頭文件
標(biāo)準(zhǔn)模塊與使用手冊
進(jìn)程
記錄
增加健壯性后的完整示例
Erlang Shell
原子類型

錯(cuò)誤處理

在討論監(jiān)督與錯(cuò)誤處理細(xì)節(jié)之前,讓我們先一起來看一下 Erlang 進(jìn)程的終止過程,或者說 Erlang 的術(shù)語 exit。

進(jìn)程執(zhí)行 exit(normal) 結(jié)束或者運(yùn)行完所有的代碼而結(jié)束都被認(rèn)為是進(jìn)程的正常(normal)終止。

進(jìn)程因?yàn)橛|發(fā)運(yùn)行時(shí)錯(cuò)誤(例如,除零、錯(cuò)誤匹配、調(diào)用不存在了函數(shù)等)而終止被稱之為異常終止。進(jìn)程執(zhí)行 exit(Reason) (注意此處的 Reason 是除 normal 以外的值)終止也被稱之為異常終止。

一個(gè) Erlang 進(jìn)程可以與其它 Erlang 進(jìn)程建立連接。如果一個(gè)進(jìn)程調(diào)用 link(Other_Pid),那么它就在其自己與 Othre_Pid 進(jìn)程之間創(chuàng)建了一個(gè)雙向連接。當(dāng)一個(gè)進(jìn)程結(jié)束時(shí),它會(huì)發(fā)送信號至所有與之有連接的進(jìn)程。

這個(gè)信號攜帶著進(jìn)程的進(jìn)程標(biāo)識(shí)符以及進(jìn)程結(jié)束的原因信息。

進(jìn)程收到進(jìn)程正常退出的信號時(shí)默認(rèn)情況下是直接忽略它。

但是,如果進(jìn)程收到的是異常終止的信號,則默認(rèn)動(dòng)作為:

  • 接收到異常終止信號的進(jìn)程忽略消息隊(duì)列中的所有消息
  • 殺死自己
  • 將相同的錯(cuò)誤消息傳遞給連接到它的所有進(jìn)程。

所以,你可以使用連接的方式把同一事務(wù)的所有進(jìn)程連接起來。如果其中一個(gè)進(jìn)程異常終止,事務(wù)中所有進(jìn)程都會(huì)被殺死。正是因?yàn)樵趯?shí)際生產(chǎn)過程中,常常有創(chuàng)建進(jìn)程同時(shí)與之建立連接的需求,所以存在這樣一個(gè)內(nèi)置函數(shù) spawn_link,與 spawn 不同之處在于,它創(chuàng)建一個(gè)新進(jìn)程同時(shí)在新進(jìn)程與創(chuàng)建者之間建立連接。

下面給出了 ping pong 示例子另外一種實(shí)現(xiàn)方法,它通過連接終止 "pong" 進(jìn)程:

-module(tut20).

-export([start/1,  ping/2, pong/0]).

ping(N, Pong_Pid) ->
    link(Pong_Pid),
    ping1(N, Pong_Pid).

ping1(0, _) ->
    exit(ping);

ping1(N, Pong_Pid) ->
    Pong_Pid ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping1(N - 1, Pong_Pid).

pong() ->
    receive
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong()
    end.

start(Ping_Node) ->
    PongPID = spawn(tut20, pong, []),
    spawn(Ping_Node, tut20, ping, [3, PongPID]).
(s1@bill)3> tut20:start(s2@kosken).
Pong received ping
<3820.41.0>
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong

與前面的代碼一樣,ping pong 程序的兩個(gè)進(jìn)程仍然都是在 start/1 函數(shù)中創(chuàng)建的,“ping”進(jìn)程在單獨(dú)的結(jié)點(diǎn)上建立的。但是這里做了一些小的改動(dòng),用到了內(nèi)置函數(shù) link?!癙ing” 結(jié)束時(shí)調(diào)用 exit(ping) ,使得一個(gè)終止信號傳遞給 “pong” 進(jìn)程,從而導(dǎo)致 “pong” 進(jìn)程終止。

也可以修改進(jìn)程收到異常終止信號時(shí)的默認(rèn)行為,避免進(jìn)程被殺死。即,把所有的信號都轉(zhuǎn)變?yōu)橐话愕南⑻砑拥叫盘柦邮者M(jìn)程的消息隊(duì)列中,消息的格式為 {'EXIT',FromPID,Reason}。我們可以通過如下的代碼來設(shè)置:

process_flag(trap_exit, true)

還有其它可以用的進(jìn)程標(biāo)志,可參閱 erlang (3)。標(biāo)準(zhǔn)用戶程序一般不需要改變進(jìn)程對于信號的默認(rèn)處理行為,但是對于 OTP 中的管理程序這個(gè)接口還是很有必要的。下面修改了 ping pong 程序來打印輸出進(jìn)程退出時(shí)的信息:

-module(tut21).

-export([start/1,  ping/2, pong/0]).

ping(N, Pong_Pid) ->
    link(Pong_Pid), 
    ping1(N, Pong_Pid).

ping1(0, _) ->
    exit(ping);

ping1(N, Pong_Pid) ->
    Pong_Pid ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    ping1(N - 1, Pong_Pid).

pong() ->
    process_flag(trap_exit, true), 
    pong1().

pong1() ->
    receive
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pong1();
        {'EXIT', From, Reason} ->
            io:format("pong exiting, got ~p~n", [{'EXIT', From, Reason}])
    end.

start(Ping_Node) ->
    PongPID = spawn(tut21, pong, []),
    spawn(Ping_Node, tut21, ping, [3, PongPID]).
(s1@bill)1> tut21:start(s2@gollum).
<3820.39.0>
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
pong exiting, got {'EXIT',<3820.39.0>,ping}
上一篇:原子類型下一篇:分布式編程