当前位置: 首页 > 面试题库 >

如何创建新的Linux内核调度程序

於子晋
2023-03-14
问题内容

通过查看调度程序源代码(2.6.34,kernel /
sched.c),我可以看到如何使用“可插拔”调度程序,并且相信可以理解要实现的接口。我还不了解的是如何将我的代码构建到内核中。至少,指向其他站点的指针将不胜感激。

现在,我在内核源代码树中为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:我已经在下面回答了我自己的问题,因为我想我已经解决了。


问题答案:

我已经找到问题的答案,所以我想在这里添加它。以下是将向2.6.34
vanilla内核添加新调度程序的补丁。现在,我只编译了内核。我完全希望运行具有此EXACT补丁的系统会导致系统崩溃-因此,使用时需要您自担风险:-)

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,


 类似资料:
  • 在进程获得的时间间隔内,谁决定这些用户线程的调度,因为内核将其视为单个进程,并不知道线程,调度是如何完成的? 如果pthreads创建用户级线程,如果需要,如何从用户空间程序创建内核级或OS线程? 根据上面的链接,它说操作系统内核提供系统调用来创建和管理线程。那么,系统调用是创建内核级线程还是用户级线程呢? 如果它创建了一个内核级线程,那么简单pthreads程序的也会显示在执行时使用clone(

  • 问题内容: 抱歉,这个问题很愚蠢。我试图在网上找到答案已有一段时间,但找不到,因此我在这里提问。我正在学习线程,并且一直在浏览此链接以及有关内核级和用户级线程的2013年Linux Plumbers Conference 2013视频 ,据我了解,使用pthreads在用户空间中创建线程,而内核并不知道关于此问题,并且仅将其视为单个进程,而不知道内部有多少个线程。在这种情况下, 内核在将进程视为时

  • 问题内容: Linux内核开发人员如何在提交代码后在本地测试他们的代码?他们是否使用某种单元测试,构建自动化?测试计划? 问题答案: linux内核非常重视社区测试。 通常,任何开发人员都会在提交之前测试他们自己的代码,并且经常会使用Linus的内核开发版本,或者与他们的工作相关的项目使用其他不稳定/开发树之一。这意味着他们经常同时测试自己的变更和其他人的变更。 正式的测试计划的方式往往不多,但是

  • 我正在使用spring-boot-starter-quartz2.2.1.release来调度Quartz作业,并且我已经在两个节点上部署了我的代码。而quartz.properties是这样的: 如果我发出了查询所有作业的请求,那么该请求可能会被发送到node1,并且只显示node1的作业。但我想同时显示node1和Node2的作业。 如果我发出了更新scanJobbyMachine1的请求,并

  • 打开文件 /etc/sysctl.conf,增加以下设置 #该参数设置系统的TIME_WAIT的数量,如果超过默认值则会被立即清除 net.ipv4.tcp_max_tw_buckets = 20000 #定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数 net.core.somaxconn = 65535 #对于还未获得对方确认的连接请求,可保存在队列中的最大数目 net.ipv4.

  • 介绍 我不会告诉你怎么在自己的电脑上去构建、安装一个定制化的 Linux 内核,这样的资料太多了,它们会对你有帮助。本文会告诉你当你在内核源码路径里敲下 make 时会发生什么。 当我刚刚开始学习内核代码时,Makefile 是我打开的第一个文件,这个文件看起来真令人害怕 :)。那时候这个 Makefile 还只包含了 1591 行代码,当我开始写本文时,内核已经是 4.2.0 的第三个候选版本