How do \"modern\" cron daemons internally schedule their jobs? Some cronds used to schedule a run every so often via at. So
A few crickets heard in this question. Good 'ol RTFC with some discrete event simulation papers and Wikipedia:
http://en.wikipedia.org/wiki/Cron#Multi-user_capability
The algorithm used by this cron is as follows:
- On start-up, look for a file named .crontab in the home directories of all account holders.
- For each crontab file found, determine the next time in the future that each command is to be run.
- Place those commands on the Franta-Maly event list with their corresponding time and their "five field" time specifier.
- Enter main loop:
- Examine the task entry at the head of the queue, compute how far in the future it is to be run.
- Sleep for that period of time.
- On awakening and after verifying the correct time, execute the task at the head of the queue (in background) with the privileges of the user who created it.
- Determine the next time in the future to run this command and place it back on the event list at that time
I wrote a blog post describing it.
Quoting the relevant text from there:
PriorityBlockingQueue (thread-safe heap) prioritized on job.nextExecutionTime().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)
}
}
}
@Override
void run()
{
while(true)
{
newJob = getNewJobFromCrontabFile() // blocking call
jobQueue.push(newJob)
}
}
@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.
jobQueueConsumerThread.interrupt()
}
}
}