【Erlang】Erlang虚拟机的内部时钟

Erlang虚拟机可视为一个小型操作系统, 有自己的一套时钟系统, 与系统时间并不是完全一致的.

Erlang虚拟机时钟使用的是 erlang:now() 获取, 系统时间使用 os:timestamp() 获取. 格式是一样的三元组: {百万秒, 秒, 微秒}.

Erlang内部时钟的特点

为什么Erlang需要实现自己的虚拟机时钟呢? 因为系统时钟有时是不可靠的, 可能会因为联网自动对时或是管理员调时钟而发生突变或往回走, Erlang虚拟机时钟就是为了避免这些问题而设计的, 它有以下几个特点:

  1. 单向: 永远不会往回走

  2. 时间间隔接近于真实: 如果在两个时间读取虚拟机时钟, 读数为T1和T2, 那么T1-T2的值接近于两个时间点的真实时间间隔.

  3. 自动修正: 如果Erlang发现虚拟机内部时钟与系统时钟读数不一致, 它会自动缓慢地修正内部时钟, 使内部时钟与系统时钟一致.

第二点是说: 如果两次读取系统时钟, 发现时间相差1小时, 不一定是真实时间过了一小时, 可能是时钟被拨快了1小时, 实际上只过了几秒 但Erlang虚拟机时钟则可以保证, 读数相差1小时, 那么实际时间过了大约一小时, 误差不超过1%.

第三点的实现方法是, Erlang发现内部时间和系统时间差距"较大"的话, 会调节内部时钟走时速度来适应外部时钟. 比方说外部时钟突然快了1分钟, Erlang会用100分钟来 …

more ...

【Erl代码片段】start_timer/3 发送的消息中的TimerRef的用途

Erlang中有两个很相似的延迟发送消息的函数, send_after/3start_timer/3, 区别仅在于前者返回Msg, 后者返回{timeout, TimerRef, Msg}. 后者的这个 TimerRef 有什么用呢?

坚强2002的博客给出了例子:

来自代码erl5.8.2\lib\stdlib-1.17.2\src\gen_fsm.erl

%% Returns Ref, sends event {timeout,Ref,Msg} after Time
%% to the (then) current state.
start_timer(Time, Msg) ->
    erlang:start_timer(Time, self(), {'$gen_timer', Msg …
more ...