夜深人静,是写代码的好时间。
在上一篇文章中我们通过 erlang 的 trace 功能了解到了打印字符串是通过消息传递来完成的。那么,同样是属于 IO,写入文件是否也是通过消息传递呢?
为此我特地写了一个简单的 trace 库, 可以把一个进程收到和发出的消息都打印出来。
我们的试验代码是这样的:
def test do
spawn(fn ->
BonyTrace.start(self())
File.write!("lol.log", "hello")
end)
end
一运行,果然打印了不少消息:
#PID<0.389.0> SENT TO: #PID<0.58.0> +0.000000s
MESSAGE: {:"$gen_call", {#PID<0.389.0>, #Reference<0.2899216400.2129133569.149481>}, {:open, "lol.log", [:binary, :write]}}
#PID<0.389.0> RECEIVED +0.000616s
MESSAGE: {#Reference<0.2899216400.2129133569.149481>, {:ok, #PID<0.391.0>}}
#PID<0.389.0> SENT TO: #PID<0.391.0> +0.000010s
MESSAGE: {:io_request, #PID<0.389.0>, #Reference<0.2899216400.2129133571.150072>, {:put_chars, :latin1, "hello"}}
#PID<0.389.0> RECEIVED +0.000175s
MESSAGE: {:io_reply, #Reference<0.2899216400.2129133571.150072>, :ok}
#PID<0.389.0> SENT TO: #PID<0.391.0> +0.000006s
MESSAGE: {:file_request, #PID<0.389.0>, #Reference<0.2899216400.2129133571.150073>, :close}
#PID<0.389.0> RECEIVED +0.000151s
MESSAGE: {:file_reply, #Reference<0.2899216400.2129133571.150073>, :ok}
#PID<0.389.0> RECEIVED +0.000004s
MESSAGE: {:DOWN, #Reference<0.2899216400.2129133571.150073>, :process, #PID<0.391.0>, :normal}
我们来解读一下:
- 首先发消息给 文件服务器, 要求 open 文件。
- 然后收到 :ok 回复,以及文件的 owner 进程。
- 向 owner 进程发送 io 请求,写入文件。
- 收到 io 回复。
- 向 owner 进程发送 file 请求,关闭文件。
- 收到 file 回复。
- 收到 owner 进程正常退出的消息。(因为 monitor 了)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。