关于后端:elixir-0069-逃离楚门的世界在beam虚拟机里做一个tracer

33次阅读

共计 1390 个字符,预计需要花费 4 分钟才能阅读完成。

当你生来是一个 beam 虚拟机里的过程,你所相熟的所有是在这个世界上,每个过程能够互相收发音讯。你所不晓得的事是,每个过程并不是同时执行的,而是由调度器进行调度。

有一天,为了探索实在的世界,你窃取了 beam 虚拟机的 bif(built in function)之一:erlang:trace 的使用权。有了它,能够监控到任意一个过程的一举一动。

要想应用它,首先须要一个过程去解决它收回来的 trace 音讯:

defmodule N1 do
  def start do
    spawn(&loop/0)
  end

  defp loop do
    receive do
      msg ->
        IO.inspect(msg)
        loop()
    end
  end
end

而后,找一个“受害者”。你找到了这个人畜有害的过程,它每 2 秒会给本人打个招呼,而后就沉沉睡去。在它安眠的时候,cpu 是否还会把关怀它呢?

defmodule N2 do
  def start do
    spawn(&loop/0)
  end

  defp loop do
    :timer.sleep(2000)
    send(self(), :hi)

    receive do
      :hi ->
        loop()
    end
  end
end

你轻轻开启了试验

iex(1)> n2 = N2.start                                 
#PID<0.155.0>
iex(2)> n1 = N1.start                                 
#PID<0.157.0>
iex(3)> :erlang.trace n2, true, [:all, {:tracer, n1}] 
1
{:trace_ts, #PID<0.155.0>, :in, {:timer, :sleep, 1}, 3, {1604, 420048, 633876}}
{:trace_ts, #PID<0.155.0>, :receive, :timeout, 3, {1604, 420048, 633890}}
{:trace_ts, #PID<0.155.0>, :send, :hi, #PID<0.155.0>, 3, {1604, 420048, 633898}}
{:trace_ts, #PID<0.155.0>, :receive, :hi, 3, {1604, 420048, 633902}}
{:trace_ts, #PID<0.155.0>, :out, {:timer, :sleep, 1}, 3, {1604, 420048, 633916}}
{:trace_ts, #PID<0.155.0>, :in, {:timer, :sleep, 1}, 3, {1604, 420050, 635069}}
{:trace_ts, #PID<0.155.0>, :receive, :timeout, 3, {1604, 420050, 635079}}
{:trace_ts, #PID<0.155.0>, :send, :hi, #PID<0.155.0>, 3, {1604, 420050, 635086}}
{:trace_ts, #PID<0.155.0>, :receive, :hi, 3, {1604, 420050, 635090}}
{:trace_ts, #PID<0.155.0>, :out, {:timer, :sleep, 1}, 3, {1604, 420050, 635098}}

机密信息被打印在了 IO 设施上,记录了一次次的 receive 和 send。最重要的是:in(进入调度器)和 out(来到调度器)的记录。你很分明地看见,在过程沉睡的 2 秒里,属于它的 cpu 工夫被窃取了。你第一次证实了已经的猜测:这是一个楚门的世界。

正文完
 0