So erstellen Sie einen neuen Linux-Kernel-Scheduler

Lesezeit: 7 Minuten

Benutzer-Avatar
J Teller

Beim Durchsehen des Scheduler-Quellcodes (2.6.34, kernel/sched.c) kann ich sehen, wie die “pluggable”-Scheduler verwendet werden, und ich glaube, ich verstehe die zu implementierende Schnittstelle. Was ich noch nicht verstehe, ist, wie ich meinen Code in den Kernel einbauen kann. Zumindest Hinweise auf andere Seiten wären willkommen.

Im Moment suche ich im Kernel-Quellbaum nach SCHED_FIFO, SCHED_RR und SCHED_NORMAL, also suche ich wirklich nach einer aufschlussreicheren Möglichkeit, es zu betrachten 🙂

BEARBEITEN: Als Hintergrund bin ich mit dem FreeBSD-Scheduler (und dem FreeBSD-Kernel im Allgemeinen) sehr vertraut, daher suche ich nicht nach Hinweisen zur Planung auf Prozess-/Thread-Ebene. Ich suche nach einer Möglichkeit, neben den normalen Linux-Schedulern (ähnlich wie SCHED_FIFO) meinen eigenen Scheduler hinzuzufügen.

EDIT #2: Der BFS-Zeiger unten ist ein guter Anfang, aber er reißt immer noch CFS aus dem Kernel. sched.c sieht jetzt so aus:

#ifdef CONFIG_SCHED_BFS
#include "sched_bfs.c"
#else
   // original sched.c 
#endif // CONFIG_SCHED_BFS

Ich würde gerne eine Antwort oder einen Hinweis darauf sehen, wie man dies ein wenig besser machen kann (dh CFS behalten, zumindest für jetzt).

EDIT #3: Ich habe unten meine eigene Frage beantwortet, da ich denke, dass ich es herausgefunden habe.

  • Meinen Sie damit, die entsprechenden Bits in kconfig hinzuzufügen, damit Ihr Scheduler ausgewählt / verwendet werden kann?

    – Tim Post

    21. Juni 2010 um 17:39 Uhr

  • Das ist ziemlich genau das, wonach ich suche – ich habe der ursprünglichen Frage (dem FreeBSD-Zeug) ein wenig Hintergrundwissen hinzugefügt, um hoffentlich klarer zu machen, wonach ich suche.

    – J Teller

    21. Juni 2010 um 20:39 Uhr

Benutzer-Avatar
J Teller

Ich habe die Antwort auf meine Frage herausgefunden, also dachte ich, ich würde sie hier hinzufügen. Unten ist der Patch, der dem Vanilla-Kernel 2.6.34 einen neuen Scheduler hinzufügt. Im Moment habe ich nur den Kernel kompiliert. Ich gehe voll und ganz davon aus, dass das Ausführen eines Systems mit diesem GENAUEN Patch zum Absturz führen wird – also verwenden Sie es auf eigene Gefahr 🙂

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2b7b81d..a2a2b21 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -37,6 +37,7 @@
 #define SCHED_RR       2
 #define SCHED_BATCH        3
 /* SCHED_ISO: reserved but not implemented yet */
+#define SCHED_NEW               4 /* Stealing from SCHED_ISO */
 #define SCHED_IDLE     5
 /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */
 #define SCHED_RESET_ON_FORK     0x40000000
diff --git a/init/Kconfig b/init/Kconfig
index eb77e8c..0055d26 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -23,6 +23,11 @@ config CONSTRUCTORS

 menu "General setup"

+config SCHED_NEW
+       bool "NEW cpu scheduler"
+       ---help---
+         Brand new scheduler 
+
 config EXPERIMENTAL
    bool "Prompt for development and/or incomplete code/drivers"
    ---help---
diff --git a/kernel/sched.c b/kernel/sched.c
index 3c2a54f..588960d 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1931,6 +1931,7 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)

 #include "sched_idletask.c"
 #include "sched_fair.c"
+#include "sched_new.c"
 #include "sched_rt.c"
 #ifdef CONFIG_SCHED_DEBUG
 # include "sched_debug.c"
diff --git a/kernel/sched_new.c b/kernel/sched_new.c
new file mode 100644
index 0000000..c2e269e
--- /dev/null
+++ b/kernel/sched_new.c
@@ -0,0 +1,140 @@
+#ifdef CONFIG_SCHED_NEW
+
+/*
+ * Starting with a simple, 1 runq per cpu scheduler.  Don't care
+ * about fairness for right now.  Just get it up and running to 
+ * verify that we have the interface correct
+ */
+
+static void
+enqueue_task_new(struct rq *rq, struct task_struct *p, int wakeup, bool head)
+{
+}
+
+static void dequeue_task_new(struct rq *rq, struct task_struct *p, int sleep)
+{
+}
+
+static void yield_task_new(struct rq *rq)
+{
+}
+
+static void check_preempt_curr_new(struct rq *rq, struct task_struct *p, int flags)
+{
+}
+
+static struct task_struct *pick_next_task_new(struct rq *rq)
+{
+}
+
+static void put_prev_task_new(struct rq *rq, struct task_struct *p)
+{
+}
+
+#ifdef CONFIG_SMP
+static int select_task_rq_new(struct task_struct *p, int sd_flag, int flags)
+{
+}
+static void pre_schedule_new(struct rq *rq, struct task_struct *prev)
+{
+}
+
+static void post_schedule_new(struct rq *rq)
+{
+}
+
+static void task_woken_new(struct rq *rq, struct task_struct *p)
+{
+}
+
+static void task_waking_new(struct rq *this_rq, struct task_struct *task)
+{
+}
+static void set_cpus_allowed_new(struct task_struct *p,
+               const struct cpumask *new_mask)
+{
+}
+/* Assumes rq->lock is held */
+static void rq_online_new(struct rq *rq)
+{
+}
+
+/* Assumes rq->lock is held */
+static void rq_offline_new(struct rq *rq)
+{
+}
+#endif /* COMFIG_SMP */
+
+static void set_curr_task_new(struct rq *rq)
+{
+}
+
+
+static void task_tick_new(struct rq *rq, struct task_struct *p, int queued)
+{
+} 
+
+static void task_fork_new(struct task_struct *p)
+{
+}
+static void switched_from_new(struct rq *rq, struct task_struct *p,
+              int running)
+{
+}
+static void switched_to_new(struct rq *this_rq, struct task_struct *task,
+               int running)
+{
+}
+static void prio_changed_new(struct rq *rq, struct task_struct *p,
+               int oldprio, int running)
+{
+}
+static unsigned int get_rr_interval_new(struct rq *rq, struct task_struct *task)
+{
+}
+
+
+
+static const struct sched_class new_sched_class = {
+   .next           = &fair_sched_class,
+   .enqueue_task       = enqueue_task_new,
+   .dequeue_task       = dequeue_task_new,
+   .yield_task     = yield_task_new,
+
+   .check_preempt_curr = check_preempt_curr_new,
+
+   .pick_next_task     = pick_next_task_new,
+   .put_prev_task      = put_prev_task_new,
+
+#ifdef CONFIG_SMP
+   .select_task_rq     = select_task_rq_new,
+
+   .pre_schedule       = pre_schedule_new,
+   .post_schedule      = post_schedule_new,
+
+   .task_waking            = task_waking_new,
+   .task_woken     = task_woken_new,
+
+   .set_cpus_allowed       = set_cpus_allowed_new,
+
+   .rq_online              = rq_online_new,
+   .rq_offline             = rq_offline_new,
+#endif
+
+   .set_curr_task          = set_curr_task_new,
+   .task_tick      = task_tick_new,
+   .task_fork              = task_fork_new,
+
+   .switched_from          = switched_from_new,
+   .switched_to        = switched_to_new,
+
+   .prio_changed       = prio_changed_new,
+
+   .get_rr_interval    = get_rr_interval_new,
+#ifdef CONFIG_FAIR_GROUP_SCHED
+   .moved_group            = NULL
+#endif
+};
+
+#endif /* CONFIG_SCHED_NEW */
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index b5b920a..aaf4beb 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1731,7 +1731,11 @@ static unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task)
 }

 static const struct sched_class rt_sched_class = {
+#ifdef CONFIG_SCHED_NEW
+   .next           = &new_sched_class,
+#else
    .next           = &fair_sched_class,
+#endif /* CONFIG_SCHED_NEW */
    .enqueue_task       = enqueue_task_rt,
    .dequeue_task       = dequeue_task_rt,
    .yield_task     = yield_task_rt,

Benutzer-Avatar
Simon Weber

Embedded.com hat einen dreiteiligen Eintrag, der durch die Implementierung eines einfachen Echtzeit-Schedulers führt:

Im Gegensatz zu den anderen Antworten wird diese als Tutorial erstellt:

[…] In der Literatur haben wir keine Dokumente gefunden, die erklären, wie man eine neue Scheduling-Policy für Linux implementiert.

[…]

In diesem Dokument haben wir in a dargestellt [sic] ausführliche Beschreibung aller Schritte, die zum Implementieren einer neuen Scheduling-Policy erforderlich sind.

[…]

Dies ist eine einfache Implementierung dieses Scheduling-Algorithmus. Fortgeschrittene Probleme wie Unterbrechungen, Timer und Multiprozessorsysteme, um nur einige zu nennen, sind jedoch nicht Gegenstand dieses Artikels.

  • Die Links sind kaputt. Ich habe sie sonst nirgendwo im Internet gefunden.

    – null keine

    26. Oktober 2015 um 16:39 Uhr

  • @zeronone sie scheinen mir heute ok zu sein. Vielleicht waren sie nur vorübergehend kaputt?

    – Simon Weber

    27. Oktober 2015 um 19:43 Uhr

  • Ja, die Links funktionieren möglicherweise nur vorübergehend

    – FoundABetterName

    8. Dezember 2021 um 12:44 Uhr

Mit Kolivas Brainfuck Scheduler. Das habe ich gerade beim googeln gefunden. Es kann ein Beispiel sein, von dem ausgegangen werden kann.

  • Ich habe mir das Design von BFS angesehen und es ist definitiv interessant. Seine Einfachheit ist genial. Ich möchte jedoch einen Scheduler hinzufügen, der mit CFS (und SCHED_FIFO usw.) koexistiert, und ich suche nach Möglichkeiten, die Konfiguration richtig hinzubekommen, nicht, wie ich den vorhandenen Scheduler herausreißen und meinen eigenen neu implementieren kann.

    – J Teller

    21. Juni 2010 um 20:41 Uhr

  • Also verbrachte ich etwas mehr Zeit damit, mir den BFS-Patch anzusehen, und ich lag falsch. Es zeigte mindestens eine Möglichkeit, einen neuen Planer hinzuzufügen, der mir eine Verknüpfung zum Hinzufügen meines Codes gab. Danke für den Hinweis blm!

    – J Teller

    22. Juni 2010 um 0:24 Uhr

1382640cookie-checkSo erstellen Sie einen neuen Linux-Kernel-Scheduler

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy