2010-06-21 92 views
27

查看调度程序源代码(2.6.34,kernel/sched.c),我可以看到如何使用“可插拔”调度程序,并且我相信我理解的接口是实现。我不明白的是如何让我的代码内置到内核中。至少,其他网站的指针将不胜感激。如何创建一个新的Linux内核调度程序

现在,我grepping为SCHED_FIFO,SCHED_RR,并在内核源代码树SCHED_NORMAL,所以我真的正在寻找一种更深入的方式来看待它:-)

编辑:由于一些背景,我对FreeBSD调度程序(以及一般的FreeBSD内核)非常熟悉,所以我不在寻找如何执行进程/线程级调度的指针。我正在寻找一种方法来将我自己的调度程序与普通的Linux调度程序(类似于SCHED_FIFO)一起添加。编辑#2:下面的BFS指针是一个很好的开始,但它仍然将CFS从内核中剥离出来。 sched.c中现在看起来像:

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

我很想看到一个答案或就如何做到这一点了更好的指针(即保持CFS,至少现在)。

编辑#3:我已经在下面回答了我自己的问题,因为我想我已经知道了。

+1

您的意思是在kconfig中添加适当的位,以便可以选择/使用您的调度程序吗? – 2010-06-21 17:39:54

+0

这正是我正在寻找的东西 - 我已经为原始问题(FreeBSD的东西)添加了一些背景,希望能够让我更加清楚地寻找到。 – 2010-06-21 20:39:52

回答

17

我已经想出了我的问题的答案,所以我想我会在这里添加它。下面是将为2.6.34 vanilla内核添加一个新调度器的补丁。现在,我只编译了内核。我完全相信运行此确切补丁的系统将导致其崩溃 - 所以需要您自担风险使用:-)

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, 
8

Con Kolivas Brainfuck Scheduler。 我刚刚通过谷歌搜索发现。这可能是一个例子。

+0

我已经浏览了BFS的设计,这绝对有趣。这简单太棒了。但是,我想添加一个与CFS(和SCHED_FIFO等)共存的调度程序,并且我正在寻找如何正确配置配置,而不是如何剔除现有调度程序并重新实现自己的配置。 – 2010-06-21 20:41:12

+4

所以,我花了一点时间看看BFS补丁,我错了。它确实显示出至少有一种方法可以添加新的调度程序,并为我提供了添加代码的快捷方式。 感谢您的指针blm! – 2010-06-22 00:24:10

13

Embedded.com具有通过实现一个简单的实走3个部分进入时间调度:

不像其他的答案,这一个被创建为一个教程:

[...]在文献中,我们没有发现,解释如何 实现对Linux新的调度策略文件。

[...]

在本文中,我们在[原文]深入的描述已经提出的所有步骤 实施新的调度策略需要。

[...]

这是一个简单的实现,调度算法的。但是,诸如中断,定时器和多处理器系统之类的高级问题,仅仅提到了一些,超出了本文的范围。

+0

链接已损坏。我无法在互联网上的任何其他地方找到他们。 – zeronone 2015-10-26 16:39:56

+0

@zeronone今天对我来说他们看起来不错。也许他们暂时被打破了? – 2015-10-27 19:43:50

+0

它现在正在工作。谢谢 :) – zeronone 2015-10-28 05:39:44