夜深人静,是写代码的好时间。

上一篇文章中我们通过 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}

我们来解读一下:

  1. 首先发消息给 文件服务器, 要求 open 文件。
  2. 然后收到 :ok 回复,以及文件的 owner 进程。
  3. 向 owner 进程发送 io 请求,写入文件。
  4. 收到 io 回复。
  5. 向 owner 进程发送 file 请求,关闭文件。
  6. 收到 file 回复。
  7. 收到 owner 进程正常退出的消息。(因为 monitor 了)。

Ljzn
399 声望102 粉丝

网络安全;函数式编程;数字货币;人工智能