最近一直在忙,偶尔有点时间在读书,补充一下能量;最近在学习 程序设计语言-实践之路 非常感慨,之前误打误撞的一点所得原来有一个更系统,完整的知识体系;于是沉下心来,慢慢吸收.像北上广这样的城市快速的代谢着我们的精力和知识,不容懈怠,不过倒也不必急躁,如果心浮气躁,效果必然大打折扣;抽时间整理一下最近的笔记,先从一个怪异的问题开始吧!
在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. abc 3> P!abcd. abcd 4> 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. abc 7> v(5)!abcd. abcd 8> 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 = 0 0x00007f738d11c2d0 Return addr 0x000000000084e1b8 (<terminate process normally>) y(0) [] y(1) value y(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) infinity ok 10> bt(v(5)). Program counter: 0x00007f73852f7ec0 (t:'-b/0-fun-0-'/0 + 8) CP: 0x000000000084e1b8 (<terminate process normally>) arity = 0 ok 11>
最后贴张图,今年银河印象的作品 车手