Как erlang реализует упреждающее планирование с одним потоком ОС?

Я хочу знать, как виртуальная машина Эрланга вытесняет работающий код и контекстирует стек. Как это можно сделать на таком языке, как с?

1 ответ

Хитрость заключается в том, что среда выполнения Erlang имеет контроль над ВМ, поэтому она может - полностью в пользовательском пространстве - отслеживать, сколько инструкций ВМ уже выполнено (или, что еще лучше, оценить или представить фактические физические вычисления, требуемые для этих инструкций). - иначе говоря, "сокращение" на языке Erlang VM) и - если это число превышает некоторый порог - немедленно поменяйте местами указатели / структуры / что угодно процесса и возобновите цикл выполнения.

Подумайте об этом как-то так (вроде псевдо-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 выполняет код операции Erlang потоками ОС, которые создаются при запуске виртуальной машины Erlang.

Код Erlang работает на виртуальных процессорах, которые управляются виртуальной машиной Erlang. И виртуальная машина Эрланга считает IO прерыванием виртуальных процессоров. Таким образом, виртуальная машина Эрланга реализует машину и планировщик как ОС. Из-за кода операции и неблокирующего ввода-вывода, мы можем реализовать прерывания в виртуальной машине Эрланга, используя язык C.

Другие вопросы по тегам