最近一直在忙,偶爾有點時間在讀書,補充一下能量;最近在學習 程式設計語言-實踐之路 非常感慨,之前誤打誤撞的一點所得原來有一個更系統,完整的知識體系;於是沉下心來,慢慢吸收.像北上廣這樣的城市快速的代謝著我們的精力和知識,不容懈怠,不過倒也不必急躁,如果心浮氣躁,效果必然大打折扣;抽時間整理一下最近的筆記,先從一個怪異的問題開始吧!
在Erlang shell中我常常建立一個無限等待接收訊息的進程來做一些測試,代碼:spawn(fun() -> receive after infinity-> io:format("DONE!") end end).問題複現步驟:1.在Erlang Shell中啟動這個進程之後 2.向該進程發送訊息 3.由於沒有訊息提取的邏輯,該進程收到的訊息就會積壓在訊息佇列裡面,可以通過erlang:process_info查看;首先使用Shell進程來試一下,可以看到結果是和我們的預期一致的:
23> [self()!abc || _<-lists:seq(1,20)].[abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc]24> erlang:process_info(self()). [{current_function,{erl_eval,do_apply,6}},{initial_call,{erlang,apply,2}},{status,running},{message_queue_len,20},{messages,[abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc,abc, abc,abc,abc,abc,abc,abc,abc,abc]},{links,[<0.26.0>]},{dictionary,[]},{trap_exit,false},{error_handler,error_handler},{priority,normal},{group_leader,<0.25.0>},{total_heap_size,5168},{heap_size,2584},{stack_size,24},{reductions,68319},{garbage_collection,[{min_bin_vheap_size,46368}, {min_heap_size,233}, {fullsweep_after,65535}, {minor_gcs,16}]},{suspending,[]}]
下面我們使用spawn(fun)的方式試一下,看下面的結果,在發送了兩條訊息之後查看進程狀態,發現訊息佇列是空的!!!
Erlang R15B (erts-5.9) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.9 (abort with ^G)1> P=spawn(fun() -> receive after infinity-> io:format("dONE!") end end).<0.34.0>2> P!abc.abc3> P!abcd.abcd4> erlang:process_info(P).[{current_function,{erl_eval,receive_clauses,8}},{initial_call,{erlang,apply,2}},{status,waiting},{message_queue_len,0},{messages,[]},{links,[]},{dictionary,[]},{trap_exit,false},{error_handler,error_handler},{priority,normal},{group_leader,<0.25.0>},{total_heap_size,233},{heap_size,233},{stack_size,10},{reductions,26},{garbage_collection,[{min_bin_vheap_size,46368}, {min_heap_size,233}, {fullsweep_after,65535}, {minor_gcs,0}]},{suspending,[]}]
難道是這樣的寫法在Erlang Shell中有問題?我就把這段代碼放在一個測試模組中試一下:
-module(t).-compile(export_all).a() -> receive {Data}-> io:format("reveive Data :~p~n ",[Data]), a() after infinity -> io:format("Done!") end.b() -> spawn(fun() -> receive after infinity-> io:format("dONE!") end end).
運行上面的代碼t:b(),發送訊息,然後查看進程狀態,$$$$~~~~~~,看到了沒有,這種寫法訊息佇列裡面是可以看到積壓的訊息的!! 那麼之前的寫法,接收到的訊息在哪裡呢?
5> t:b().<0.39.0>6> v(5)!abc.abc7> v(5)!abcd.abcd8> erlang:process_info(v(5)).[{current_function,{t,'-b/0-fun-0-',0}},{initial_call,{erlang,apply,2}},{status,waiting},{message_queue_len,2},{messages,[abc,abcd]},{links,[]},{dictionary,[]},{trap_exit,false},{error_handler,error_handler},{priority,normal},{group_leader,<0.25.0>},{total_heap_size,233},{heap_size,233},{stack_size,0},{reductions,2},{garbage_collection,[{min_bin_vheap_size,46368}, {min_heap_size,233}, {fullsweep_after,65535}, {minor_gcs,0}]},{suspending,[]}]
訊息有可能在哪裡呢?還有一個辦法,我們把stacktrace輸出一下,從下面的結果中我們可以看到一點端倪:進程P的堆棧資訊中y(2) [abcd,abc]就是之前我們香它發送的訊息;查看一下t:b()進程,並沒有看到類似的資訊;通過對比,突破點應該在這裡,但是苦於沒有找到process_dsiplay輸出資訊的詳細說明,難以繼續了,記錄於此,日後繼續
9> bt(P).Program counter: 0x00007f738b7d76c0 (erl_eval:receive_clauses/8 + 168)CP: 0x0000000000000000 (invalid)arity = 00x00007f738d11c2d0 Return addr 0x000000000084e1b8 (<terminate process normally>)y(0) []y(1) valuey(2) [abcd,abc]y(3) {value,#Fun<shell.7.20862592>}y(4) {eval,#Fun<shell.24.20862592>}y(5) []y(6) {[{call,1,{remote,1,{atom,1,io},{atom,1,format}},[{string,1,"dONE!"}]}],[]}y(7) []y(8) infinityok10> bt(v(5)).Program counter: 0x00007f73852f7ec0 (t:'-b/0-fun-0-'/0 + 8)CP: 0x000000000084e1b8 (<terminate process normally>)arity = 0ok11>
最後貼張圖,今年銀河印象的作品 車手