erlang - erlang是如何用一个OS线程实现抢占式调度的?

标签 erlang scheduling preemptive green-threads

我想知道 erlang 的 VM 如何抢占正在运行的代码并上下文堆栈。如何用 c 之类的语言来完成?

最佳答案

诀窍在于 Erlang 运行时可以控制 VM,因此它可以——完全在用户空间——跟踪它已经执行了多少 VM 指令(或者,更好的是,估计或表示所需的实际物理计算对于那些指令——在 Erlang VM 的说法中也称为“减少”)并且——如果这个数字超过某个阈值——立即交换进程指针/结构/任何东西并恢复执行循环。

可以这样想(类似于伪 C,可能实际上是 C,也可能不是 C,但我不知道,因为我不是 C 程序员,但你问过你会怎么做它在 C 中,所以我会尝试我最大胆的):

void proc_execute(Proc* proc)
{
    /* I don't recall if Erlang's VM supports different
       reduction limits for different processes, but if it
       did, it'd be a rather intuitive way to define process
       priorities, i.e. making sure higher-priority processes
       get more reductions to spend */
    int rds = proc->max_reductions;

    for (; rds > 0; rds--) {
        /* Different virtual instructions might execute different numbers of
           physical instructions, so vm_execute_next_instruction will return
           however many reductions are left after executing that virtual
           instruction. */
        rds = vm_execute_next_instruction(proc, rds);
        if (proc->exited) break;
    }
}

void vm_loop(Scheduler* sched)
{
    Proc *proc;

    for (;;) {
        proc = sched_next_in_queue(sched);
        /* we'll assume that the proc will be null if the
           scheduler doesn't have any processes left in its
           list */
        if (!proc) break;
        proc_execute(proc);
    }
}

Proc* sched_next_in_queue(Scheduler* sched)
{
    if (!sched->current_proc->exited) {
        /* If the process hasn't exited yet, readd it to the
           end of the queue so we can resume running it
           later */
        shift(sched->queue, sched->current_proc);
    }
    sched->current_proc = pop(sched->queue);
    return sched->current_proc;
}

这显然是相当简化的(特别是排除/省略了很多重要的东西,比如 VM 指令是如何实现的以及消息是如何传递的),但希望它说明了(如果我理解正确的话,至少)Erlang 的抢占式调度程序和流程模型在基础层面上工作。

关于erlang - erlang是如何用一个OS线程实现抢占式调度的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49079624/

相关文章:

erlang - 为什么 EUnit 将 .beam 文件编译成 .eunit/ebin?

sql-server - 确定 SQL Server 计划在一段时间内何时触发?

LLVM 指令调度

xamarin - Dotfuscator UWP 命令已退出,代码为 1

Erlang编译器错误

Erlang:获取多主机集群上所有节点的列表

hadoop - 如何依次依次运行MapReduce作业

java - Java 是抢占式的吗?

erlang - dets 会在使用 ram_file 选项查找时执行磁盘读取吗?