cron如何在内部安排工作?

时间:2010-10-20 22:56:30

标签: linux unix cron crontab scheduler

“现代”cron守护进程内部如何安排工作?有些crond用于通过at每隔一段时间安排一次运行。因此,在写出crontab之后,crond

  1. 解析所有未来事件的crontab和间隔的睡眠状态?
  2. 每分钟轮询一次聚合的crontab数据库,以确定当前时间是否与计划模式匹配?
  3. 其他?
  4. 谢谢,

2 个答案:

答案 0 :(得分:51)

在这个问题上听到了一些蟋蟀。很好的RTFC和一些离散事件模拟论文和维基百科:

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

  

此cron使用的算法为   如下:

     
      
  1. 在启动时,在主目录中查找名为.crontab的文件   所有账户持有人。
  2.   
  3. 对于找到的每个crontab文件,确定将来的下一次   每个命令都要运行。
  4.   
  5. 将这些命令放在Franta-Maly事件列表中   相应的时间和他们的“五   字段“时间说明符。
  6.   
  7. 输入主循环:      
        
    1. 检查队列头部的任务条目,计算其中的距离   未来它将被运行。
    2.   
    3. 睡了一段时间。
    4.   
    5. 在唤醒时和验证正确的时间后,执行任务   队列的头部(在后台)   具有用户权限   创造了它。
    6.   
    7. 确定将来下次运行此命令和放置的时间   它回到当时的事件清单上
    8.   
  8.   

答案 1 :(得分:4)

我写了一个blog post来描述它。
从那里引用相关文本:

  • 我们可以有一个有限的线程池,它将通过优先于PriorityBlockingQueue的{​​{1}}(线程安全堆)来执行所有任务。
  • 这意味着该堆的顶部元素将始终是最早触发的元素。
  • 我们将遵循标准的线程池生产者-消费者模式。
  • 我们将有一个线程将无限循环地运行,并在从队列中消耗掉新作业后将新作业提交到线程池。 让我们称之为 QueueConsumerThread
job.nextExecutionTime()
  • 还有一个线程将监视crontab文件中是否有任何新作业添加,并将其推入队列。
  • 我们称它为 QueueProducerThread
void goToSleep(job, jobQueue){
    jobQueue.push(job);
    sleep(job.nextExecutionTime() - getCurrentTime());
}

void executeJob(job, jobQueue){
    threadpool.submit(job); // async call
    job = job.copy();
    job.setNextExecutionTime(getCurrentTime() + job.getExecutionInterval());
    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)
        }
    }
}
  • 但是,这有一个问题:
    • 想象一下,Thread1正在睡眠,一个小时后就会醒来。
    • 与此同时,应该每分钟运行一次新任务。
    • 这个新任务要等一个小时后才能开始执行。
  • 要解决此问题,只要新任务必须比队列中的前一个任务运行得早,我们就可以强制ProducerThread从其睡眠中唤醒ConsumerThread:
@Override
void run()
{
    while(true)
    {
        newJob = getNewJobFromCrontabFile() // blocking call
        jobQueue.push(newJob)
    }
}