Linux 默认调度程序替代方案
Linux default scheduler alternatives
Linux 内核实现 Completely Fair Scheduling (SCHED_NORMAL)
算法作为其调度实时进程的默认调度算法。
如何修改 linux 内核,以便将默认调度策略设置为 round-robin (SCHED_RR)
或任何其他调度策略?有通用的方法吗?这里需要准确更改哪些文件?
我正在 Ubuntu 16.04.
我查看了内核代码,SCHED_NORMAL
实际上在几个地方是 hard-coded,例如https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/sched/core.c#n2394
可能可以在所有地方将其更改为 SCHED_RR
,但正如评论中所写,不建议这样做。它可能会使您的系统崩溃,因为,例如,long-running 计算将阻止 CPU.
无论如何,请告诉我这只是一个实验 :) 我真的看不出尝试这种异端有什么好处。
也就是说,这是我的尝试。首先,我们需要得到一个沙箱。我使用了用户模式 Linux (UML)。对于内核,我随机抓取了一个 4.10.0-rc1 存储库,但任何版本都可以。对于 rootfs,UML 页面提供了其中的一堆 here(陷阱:并非所有这些都可以正常工作)。
构建内核的步骤非常短:
export ARCH=um
make x86_64_defconfig
make
如果您有 Slackware rootfs,您现在可以 运行 作为:
./vmlinux ubda=./Slamd64-12.1-root_fs
好的,酷。所以我们有一个安全的地方来破坏一些内核。让我们开始吧。您可能知道,init
(pid=1) 是第一个进程,也是所有其他进程的父进程。 RT 调度 class 是继承的(除非用标志另外询问,参见 man 7 sched 中的 SCHED_RESET_ON_FORK)。这意味着我们可以更改 init
进程的调度 class 并让其子进程默认继承调度 class。
这很容易通过这样的方式实现:
diff --git a/init/main.c b/init/main.c
index b0c9d6facef9..015f72b318ef 100644
--- a/init/main.c
+++ b/init/main.c
@@ -951,8 +951,11 @@ static inline void mark_readonly(void)
static int __ref kernel_init(void *unused)
{
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
int ret;
+ /* Sit tight and fasten your seat belt! */
+ sched_setscheduler_nocheck(current, SCHED_FIFO, ¶m);
kernel_init_freeable();
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
而且有效!
root@darkstar:~# sleep 60 &
[1] 549
root@darkstar:~# ps -c
PID CLS PRI TTY TIME CMD
536 FF 139 tty0 00:00:00 bash
549 FF 139 tty0 00:00:00 sleep
550 FF 139 tty0 00:00:00 ps
(顺便说一句,SCHED_DEADLINE不能继承,如man 7 sched中所述)。
Linux 内核实现 Completely Fair Scheduling (SCHED_NORMAL)
算法作为其调度实时进程的默认调度算法。
如何修改 linux 内核,以便将默认调度策略设置为 round-robin (SCHED_RR)
或任何其他调度策略?有通用的方法吗?这里需要准确更改哪些文件?
我正在 Ubuntu 16.04.
我查看了内核代码,SCHED_NORMAL
实际上在几个地方是 hard-coded,例如https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/sched/core.c#n2394
可能可以在所有地方将其更改为 SCHED_RR
,但正如评论中所写,不建议这样做。它可能会使您的系统崩溃,因为,例如,long-running 计算将阻止 CPU.
无论如何,请告诉我这只是一个实验 :) 我真的看不出尝试这种异端有什么好处。
也就是说,这是我的尝试。首先,我们需要得到一个沙箱。我使用了用户模式 Linux (UML)。对于内核,我随机抓取了一个 4.10.0-rc1 存储库,但任何版本都可以。对于 rootfs,UML 页面提供了其中的一堆 here(陷阱:并非所有这些都可以正常工作)。
构建内核的步骤非常短:
export ARCH=um
make x86_64_defconfig
make
如果您有 Slackware rootfs,您现在可以 运行 作为:
./vmlinux ubda=./Slamd64-12.1-root_fs
好的,酷。所以我们有一个安全的地方来破坏一些内核。让我们开始吧。您可能知道,init
(pid=1) 是第一个进程,也是所有其他进程的父进程。 RT 调度 class 是继承的(除非用标志另外询问,参见 man 7 sched 中的 SCHED_RESET_ON_FORK)。这意味着我们可以更改 init
进程的调度 class 并让其子进程默认继承调度 class。
这很容易通过这样的方式实现:
diff --git a/init/main.c b/init/main.c
index b0c9d6facef9..015f72b318ef 100644
--- a/init/main.c
+++ b/init/main.c
@@ -951,8 +951,11 @@ static inline void mark_readonly(void)
static int __ref kernel_init(void *unused)
{
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
int ret;
+ /* Sit tight and fasten your seat belt! */
+ sched_setscheduler_nocheck(current, SCHED_FIFO, ¶m);
kernel_init_freeable();
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
而且有效!
root@darkstar:~# sleep 60 &
[1] 549
root@darkstar:~# ps -c
PID CLS PRI TTY TIME CMD
536 FF 139 tty0 00:00:00 bash
549 FF 139 tty0 00:00:00 sleep
550 FF 139 tty0 00:00:00 ps
(顺便说一句,SCHED_DEADLINE不能继承,如man 7 sched中所述)。