80 Stimmen

Wie plant cron intern Aufträge?

Wie können "moderne" cron Dämonen intern ihre Arbeit planen? Einige crond s verwendet, um einen Lauf zu planen, und zwar über at . Nachdem also eine crontab geschrieben wurde, muss crond :

  1. Die Crontab für alle zukünftigen Ereignisse und den Sleep für die Intervalle auswerten?
  2. Jede Minute eine aggregierte Crontab-Datenbank abfragen, um festzustellen, ob die aktuelle Zeit mit dem Zeitplanmuster übereinstimmt?
  3. Andere?

Danke,

92voto

Jé Queue Punkte 9947

Ein paar Grillen in dieser Frage gehört. Das gute alte RTFC mit einigen Papieren zur diskreten Ereignissimulation und Wikipedia:

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

Der von diesem Cron verwendete Algorithmus ist der folgende wie folgt:

  1. Suchen Sie beim Start nach einer Datei namens .crontab in den Home-Verzeichnissen aller Kontoinhaber.
  2. Für jede gefundene crontab-Datei wird der nächste Zeitpunkt in der Zukunft bestimmt dass jeder Befehl ausgeführt werden soll.
  3. Setzen Sie diese Befehle in die Franta-Maly-Ereignisliste mit ihren entsprechenden Zeit und ihrem "Fünf Feld"-Zeitangabe.
  4. Hauptschleife betreten:
    1. Untersuchen Sie den Aufgabeneintrag an der Spitze der Warteschlange, berechnen Sie, wie weit in der Zukunft er ausgeführt werden soll.
    2. Schlafen Sie für diese Zeitspanne.
    3. Nach dem Aufwachen und nach Überprüfung der korrekten Zeit, führen Sie die Aufgabe am an der Spitze der Warteschlange (im Hintergrund) mit den Rechten des Benutzers aus, der der sie erstellt hat.
    4. Bestimmen Sie, wann dieser Befehl das nächste Mal ausgeführt werden soll, und setzen Sie zu diesem Zeitpunkt wieder in die Ereignisliste aufnehmen

15voto

Anmol Singh Jaggi Punkte 7829

Ich schrieb eine Blogbeitrag zu beschreiben.
Ich zitiere den entsprechenden Text von dort:

  • Wir können einen endlichen Thread-Pool haben, der alle Aufgaben ausführt, indem er sie von einem PriorityBlockingQueue (thread-safe heap) priorisiert auf job.nextExecutionTime() .

  • Das bedeutet, dass das oberste Element dieses Haufens immer dasjenige sein wird, das am schnellsten ausgelöst wird.

  • Wir werden dem Standard-Threadpool-Producer-Consumer-Muster folgen.

  • Wir werden einen Thread haben, der in einer Endlosschleife läuft und neue Aufträge an den Thread-Pool weiterleitet, nachdem er sie aus der Warteschlange abgeholt hat. Nennen wir ihn 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) } } }

  • Es wird einen weiteren Thread geben, der die crontab-Datei auf neue Aufträge überwacht und diese in die Warteschlange stellt.

  • Nennen wir es QueueProducerThread :

    @Override void run() { while(true) { newJob = getNewJobFromCrontabFile() // blocking call jobQueue.push(newJob) } }

  • Allerdings gibt es dabei ein Problem:

    • Stellen Sie sich vor, dass Thread1 schläft und nach einer Stunde wieder aufwacht.
    • In der Zwischenzeit trifft eine neue Aufgabe ein, die jede Minute ausgeführt werden soll.
    • Diese neue Aufgabe wird erst eine Stunde später ausgeführt werden können.
  • Um dieses Problem zu lösen, kann der ProducerThread den ConsumerThread zwangsweise aus dem Ruhezustand aufwecken, wenn die neue Aufgabe früher laufen muss als die vorderste Aufgabe in der Warteschlange:

    @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() } } }

Beachten Sie, dass dies möglicherweise nicht die interne Implementierung von cron ist. Dies ist jedoch die optimalste Lösung, die ich mir vorstellen kann. Sie erfordert kein Polling und alle Threads schlafen, bis sie Arbeit verrichten müssen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X