標籤:erlang 入門教程 application link
1、樣本項目(bank)簡介
bank_server.erl是為客戶服務的進程回調模組
bank_center.erl是為銀行服務中心的進程回調模組
客戶(bank_server)每年都要扣除年費
所有年費都交給銀行服務中心(bank_center)
客戶服務使用樣本:
建立使用者:bank_server:create_account(myname, 100).
使用者存錢:myname ! {deposit, 10}.
使用者取錢:myname ! {cash1, 20}.
myname ! {cash2, 30}.
查詢餘額:myname ! check.
銀行服務中心使用樣本:
查詢收到的年費總額:bank_center ! check.
2、啟動bank_center2.1、bank_center裡有3個啟動API
%% 此處?MODULE為bank_centerstart()->%% gen_server:start/3%% 無link,無註冊{ok, Pid} = gen_server:start(?MODULE, [], []),%% 自行註冊erlang:register(?MODULE, Pid).start2()->%% gen_server:start/4%% 無link,註冊為本地進程,名稱為?MODULEgen_server:start({local, ?MODULE}, ?MODULE, [], []).start_link()->%% gen_server:start_link/4%% 有link,有註冊gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
用start/0或start2/0是無link的,start_link/0是有link的。
2.2、在bank_app裡啟動bank_center
-module(bank_app).-behaviour(application). -export([start/2, stop/1]). -include("common.hrl").start(_Type, _Args) -> ?I("Start ~p ...", [?MODULE]),% bank_center:start(),% bank_center:start2(),bank_center:start_link(),{ok, self()}.stop(_State) -> ?I("Stop ~p!", [?MODULE]),ok.
在上面start/2裡調用bank_center:start/0或bank_center:start2/0啟動後,
執行appmon:start()查看bank進程,如下:
在上面start/2裡調用bank_center:start_link/0啟動後,
執行appmon:start()查看bank進程,如下:
3、建立客戶進程後,和bank_center進行linkbank_server.erl中的init/1
init([Money]) ->%% 與銀行服務中心進行關聯link(whereis(bank_center)),{ok, Money}.
4、link實驗4.1、測試link的作用link方式啟動bank_center並且建立一個客戶:
bank_server:create_account(myname1, 100).
whereis(bank_center)查看bank_center進程ID,返回不為undefined說明bank_center進程存在
向客戶進程發送一個錯誤:
myname1 ! error.
此時myname1異常退出,whereis(bank_center)和whereis(myname1)都返回undefined,說明這兩個進程都已經終止。
Eshell V5.10.4 (abort with ^G)1> bank_server:create_account(myname1, 100).true2> whereis(bank_center).<0.37.0>3> myname1 ! error.##[<0.38.0>bank_server:141] terminate: {bad_return_value,{ok,80}}error4> =ERROR REPORT==== 16-Jan-2015::16:54:58 ===** Generic server <0.38.0> terminating ** Last message in was error** When Server state == 80** Reason for termination == ** {bad_return_value,{ok,80}}4> whereis(bank_center).undefined5> whereis(myname1). undefined
小結:用link進行關聯的進程組中,只要其中一個進程終止,其他也會同時終止。
4.2、設定bank_center為系統進程,並且能監控客戶進程的退出設定bank_center為系統進程:
bank_center.erl中的init/1
init(_) ->%% 把系統進程設定為系統進程process_flag(trap_exit, true),?I("Start ~p ...", [?MODULE]),{ok, 0}.示範過程如下:
Eshell V5.10.4 (abort with ^G)1> bank_server:create_account(myname1, 100).true2> 2> myname1 ! error.##[<0.38.0>bank_server:141] terminate: {bad_return_value,{ok,100}}##[<0.37.0>bank_center:81] handle_info: {'EXIT',<0.38.0>,{bad_return_value,{ok,100}}}error3> =ERROR REPORT==== 16-Jan-2015::17:12:34 ===** Generic server <0.38.0> terminating ** Last message in was error** When Server state == 100** Reason for termination == ** {bad_return_value,{ok,100}}3> whereis(bank_center).<0.37.0>4> whereis(myname1). undefinedwhereis(myname1).返回undefined說明已經終止。
whereis(bank_center)返回了PID,說明沒有終止,並且收到了myname1的退出訊息:
{'EXIT', <0.38.0>, {bad_return_value,{ok,100}}}訊息中指明了退出的PID及退出原因。
以上都是以異常的方式讓進程退出的,現在測試一下正常退出的情況:
Eshell V5.10.4 (abort with ^G)1> bank_server:create_account(myname1, 100).true2> myname1 ! stop2.##[<0.38.0>bank_server:141] terminate: normal##[<0.37.0>bank_center:81] handle_info: {'EXIT',<0.38.0>,normal}stop2正常退出不會報錯,收到了正常退出訊息:{‘EXIT‘,<0.38.0>,normal}
小結:通過process_flag(trap_exit, true)將進程設定為系統,不但不會隨著別的進程退出而退出,還能監控其他進程的退出情況。
問題:如果系統進程內部發生了錯誤而異常退出,將會出現什麼情況?
5、完整示範代碼下載
地址:http://download.csdn.net/detail/u011471961/8368973
Erlang入門:構建application練習4(進程link的作用)