Как cron внутренне планирует задания?

Как «современные» cron демоны внутренне планируют свою работу? Некоторые cronds использовали время для планирования прогона через at. Итак, после того, как crontab записан, выполняется crond:

  1. Разбирать crontab для всех будущих событий и сна для интервалов?
  2. Опрашивать агрегированную базу данных crontab каждую минуту, чтобы определить, соответствует ли текущее время шаблону расписания?
  3. Другой?

Спасибо,


person Jé Queue    schedule 20.10.2010    source источник


Ответы (2)


Несколько сверчков услышали в этом вопросе. Старый добрый RTFC с некоторыми документами по моделированию дискретных событий и Википедией:

http://en.wikipedia.org/wiki/Cron#Multi-user_capability

Алгоритм, используемый этой cron, выглядит следующим образом:

  1. При запуске найдите файл с именем .crontab в домашних каталогах всех владельцев учетных записей.
  2. Для каждого найденного файла crontab определите, когда в следующий раз будет выполняться каждая команда.
  3. Поместите эти команды в список событий Франта-Малы, указав соответствующее время и указав их "пять полей" спецификатора времени.
  4. Enter main loop:
    1. Examine the task entry at the head of the queue, compute how far in the future it is to be run.
    2. Спите в течение этого времени.
    3. После пробуждения и проверки правильного времени выполните задачу в начале очереди (в фоновом режиме) с привилегиями пользователя, который ее создал.
    4. Определите следующий раз в будущем, чтобы запустить эту команду, и поместите ее обратно в список событий в это время.
person Jé Queue    schedule 10.11.2010
comment
Судя по странице man для cron, похоже, что он просыпается каждую минуту, чтобы проверить, следует ли запускать задание: cron затем просыпается каждую минуту, проверяя все сохраненные crontab, проверяя каждую команду, чтобы увидеть, следует ли ее запускать в текущем минута. Это от Vixie Cron, установленного на Debian (написано Полом Викси). Я думаю, что описанный вами алгоритм использовался, когда каждую минуту просыпаться было слишком дорого. - person Paul; 14.09.2016
comment
Я хотел бы найти описание списка мероприятий franta-maly где-нибудь в Интернете. Это обычная структура данных? - person Tyler Brock; 28.01.2018
comment
@TylerBrock, я полагаю, OP имеет в виду Франту, У. Р. и Курта Мали. Эффективная структура данных для набора событий моделирования. Университет Миннесоты, staff.ii.pw.edu.pl/~ gjb / aal / index_lists.pdf. - person Aaron Blenkush; 18.12.2018
comment
Прекрасно, спасибо @AaronBlenkush! Некоторое время пытался ответить на этот вопрос. - person Tyler Brock; 15.01.2019
comment
Как работает сон внутри? Я имею в виду, как компьютер узнает, что что-то ожидало X миллисекунд и что сейчас самое время начать что-то делать? - person ifly6; 21.08.2019
comment
@ ifly6 короткий упрощенный ответ заключается в том, что процесс может сказать планировщику процессов ядра, чтобы он разбудил его через определенное время. Планировщик процессов использует аппаратное обеспечение ЦП для отслеживания времени. Конечно, есть гораздо больше возможностей для планирования процессов, чем поместится в комментарии. - person Vinay Pai; 16.10.2019
comment
Но представьте, что на шаге 4.1, если следующая задача должна выполняться через час, cron перейдет в спящий режим на час. Но пока он спит, добавляется новая задача, которая должна выполняться каждую минуту. Как он справится с таким делом? - person Anmol Singh Jaggi; 08.05.2020

Я написал сообщение в блоге с описанием этого. < br /> Цитата оттуда:

  • У нас может быть конечный пул потоков, который будет выполнять все задачи, забирая их из PriorityBlockingQueue (потокобезопасной кучи) с приоритетом job.nextExecutionTime().
  • Это означает, что верхний элемент этой кучи всегда будет тем, который сработает быстрее всего.
  • Мы будем следовать стандартному шаблону производитель-потребитель пула потоков.
  • У нас будет один поток, который будет работать в бесконечном цикле и отправлять новые задания в пул потоков после их использования из очереди. Назовем его QueueConsumerThread:
void goToSleep(job, jobQueue){
    jobQueue.push(job);
    sleep(job.nextExecutionTime() - getCurrentTime());
}

void executeJob(job, jobQueue){
    threadpool.submit(job); // async call
    if (job.isRecurring()) {
        job = job.copy().setNextExecutionTime(getCurrentTime() + job.getRecurringInterval());
        jobQueue.add(job);
    }
}

@Override
void run(){
    while(true)
    {
        job = jobQueue.pop()
        if(job.nextExecutionTime() > getCurrentTime()){
            // Nothing to do
            goToSleep(job, jobQueue)
        }
        else{
            executeJob(job, jobQueue)
        }
    }
}
  • Будет еще один поток, который будет отслеживать файл crontab на предмет любых новых добавлений заданий и помещать их в очередь.
  • Назовем его QueueProducerThread:
@Override
void run()
{
    while(true)
    {
        newJob = getNewJobFromCrontabFile() // blocking call
        jobQueue.push(newJob)
    }
}
  • However, there is a problem with this:
    • Imagine that Thread1 is sleeping and will wake up after an hour.
    • Тем временем появляется новая задача, которая должна выполняться каждую минуту.
    • Эта новая задача сможет начать выполнение только через час.
  • Чтобы решить эту проблему, мы можем заставить ProducerThread пробудить ConsumerThread из спящего режима принудительно, когда новая задача должна выполняться раньше, чем передняя задача в очереди:
@Override
void run()
{
    while(true)
    {
        newJob = getNewJobFromCrontabFile() // blocking call
        jobQueue.push(newJob)
        if(newJob == jobQueue.peek())
        {
            // The new job is the one that will be scheduled next.
            // So wakeup consumer thread so that it does not oversleep.
            consumerThread.interrupt()
        }
    }
}

Обратите внимание, что это может быть не так, как внутренняя реализация cron. Однако это самое оптимальное решение, которое я могу придумать. Это не требует опроса, и все потоки спят, пока им не понадобится выполнять какую-либо работу.

person Anmol Singh Jaggi    schedule 09.05.2020