我读到据说可以通过写入 /sys/block/[disk]/queue/scheduler 来更改正在运行的内核上特定设备的 I/O 调度程序。 例如我可以在我的系统上看到:
anon@anon:~$ cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]
默认是完全公平的排队调度程序。 我想知道在我的自定义内核中包含所有四个调度程序是否有任何用处。 编译多个调度程序似乎没有多大意义,除非内核足够聪明,可以为正确的硬件选择正确的调度程序,特别是用于基于闪存的驱动器的“noop”调度程序以及用于传统驱动器的其他调度程序之一。硬盘。
是这样吗?
/usr/src/linux/Documentation/block/switching-sched.txt
中所述,任何特定块设备上的 I/O 调度程序都可以在运行时更改。可能会存在一些延迟,因为在使用新调度程序之前,之前的调度程序的请求已全部刷新,但即使在设备大量使用时也可以毫无问题地进行更改。
# cat /sys/block/hda/queue/scheduler
noop deadline [cfq]
# echo deadline > /sys/block/hda/queue/scheduler
# cat /sys/block/hda/queue/scheduler
noop [deadline] cfq
理想情况下,应该有一个调度程序来满足所有需求。 它似乎还不存在。 内核通常没有足够的知识来为您的工作负载选择最佳的调度程序:
noop
通常是内存支持的块设备(例如 ramdisk)和其他非旋转介质(闪存)的最佳选择,在这些设备中尝试重新调度 I/O 会浪费资源deadline
是一个轻量级调度程序,它试图对延迟进行严格限制cfq
尝试维持系统范围内 I/O 带宽的公平性默认值是
anticipatory
很长一段时间,并且接受了很多调整,但在2.6.33(2010年初)中被删除。 cfq
不久前成为默认设置,因为它的性能合理且公平性对于多用户系统(甚至单用户桌面)来说是一个很好的目标。 对于某些场景 - 数据库经常被用作示例,因为它们往往已经有自己独特的调度和访问模式,并且通常是“最”重要的服务(所以谁关心公平性?) - anticipatory
有一个在这些工作负载上可调节以获得最佳性能的悠久历史,并且deadline
非常快速地将所有请求传递到底层设备。
# set noop scheduler for non-rotating disks
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="noop"
在新的 udev 规则文件中(例如,
/etc/udev/rules.d/60-ssd-scheduler.rules
)。这个答案基于
debian wiki要检查SSD盘是否会使用该规则,可以提前检查触发器属性:
for f in /sys/block/sd?/queue/rotational; do printf "$f "; cat $f; done
在现代服务器级硬件上,只有 noop 似乎完全有用。在我的测试中其他人似乎较慢。
示例:
elevator=deadline
这将使“deadline”成为所有块设备的默认 I/O 调度程序。
如果您想在系统启动后查询或更改调度程序,或者想对特定块设备使用不同的调度程序,我建议安装并使用工具
ioschedset来简化此操作。
https://github.com/kata198/ioschedset如果您使用的是 Archlinux,它可以在 aur 中使用:
https://aur.archlinux.org/packages/ioschedset一些示例用法:
# Get i/o scheduler for all block devices
[username@hostname ~]$ io-get-sched
sda: bfq
sr0: bfq
# Query available I/O schedulers
[username@hostname ~]$ io-set-sched --list
mq-deadline kyber bfq none
# Set sda to use "kyber"
[username@hostname ~]$ io-set-sched kyber /dev/sda
Must be root to set IO Scheduler. Rerunning under sudo...
[sudo] password for username:
+ Successfully set sda to 'kyber'!
# Get i/o scheduler for all block devices to assert change
[username@hostname ~]$ io-get-sched
sda: kyber
sr0: bfq
# Set all block devices to use 'deadline' i/o scheduler
[username@hostname ~]$ io-set-sched deadline
Must be root to set IO Scheduler. Rerunning under sudo...
+ Successfully set sda to 'deadline'!
+ Successfully set sr0 to 'deadline'!
# Get the current block scheduler just for sda
[username@hostname ~]$ io-get-sched sda
sda: mq-deadline
用法应该是不言自明的。这些工具是独立的,只需要 bash。
希望这有帮助!
编辑:免责声明,这些是我写的脚本。
更改 IO 调度程序。 默认调度程序是在启动时根据 /linux-2.6
/block/Kconfig.iosched 文件中的内容选择的。但是,可以通过将有效的调度程序名称添加到位于 /sys/block/[DEV]/queue/scheduler 的文件中来在运行时更改 IO 调度程序。例如,echo