84

我读到可以通过写入 /sys/block/[disk]/queue/scheduler 来更改正在运行的内核上特定设备的 I/O 调度程序。例如,我可以在我的系统上看到:

anon@anon:~$ cat /sys/block/sda/queue/scheduler 
noop anticipatory deadline [cfq] 

默认是完全公平的排队调度程序。我想知道在我的自定义内核中包含所有四个调度程序是否有任何用处。除非内核足够聪明,可以为正确的硬件选择正确的调度程序,特别是用于基于闪存的驱动器的“noop”调度程序以及用于传统驱动器的其他调度程序,否则编译多个调度程序似乎没有多大意义硬盘。

是这样吗?

4

5 回答 5

110

如 中/usr/src/linux/Documentation/block/switching-sched.txt所述,任何特定块设备上的 I/O 调度程序都可以在运行时更改。可能会有一些延迟,因为在使用新的调度器之前,之前的调度器的请求都被刷新了,但是即使设备被大量使用,也可以毫无问题地更改它。

# cat /sys/block/hda/queue/scheduler
noop deadline [cfq]
# echo anticipatory > /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非常快速地将所有请求传递到底层设备。

于 2009-06-18T02:59:19.227 回答
20

可以使用 udev 规则让系统根据硬件的某些特性来决定调度程序。
SSD 和其他非旋转驱动器的示例 udev 规则可能如下所示

# 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 磁盘是否会使用该规则,可以提前检查 trigger 属性:

for f in /sys/block/sd?/queue/rotational; do printf "$f "; cat $f; done
于 2016-02-03T10:20:50.040 回答
7

让内核支持不同的内核的目的是您可以在不重新启动的情况下试用它们;然后,您可以通过系统运行测试工作负载,测量性能,然后将其作为您的应用程序的标准工作负载。

在现代服务器级硬件上,只有 noop 似乎完全有用。在我的测试中,其他人似乎更慢。

于 2009-06-17T21:24:42.007 回答
0

您可以在启动时通过将“elevator”参数添加到内核 cmdline(例如在 grub.cfg 中)来设置它

例子:

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。

希望这可以帮助!

编辑:免责声明,这些是我写的脚本。

于 2018-12-11T21:27:38.440 回答
-3

Linux 内核不会在运行时自动更改 IO 调度程序。我的意思是,截至今天,Linux 内核无法根据辅助存储设备的类型自动选择“最佳”调度程序。在启动期间或运行期间,可以手动更改 IO 调度程序。

默认调度程序是在启动时根据位于 /linux-2.6 /block/Kconfig.iosched的文件中的内容选择的。echo但是,可以通过在位于 /sys/block/[DEV]/queue/scheduler 的文件中输入有效的调度程序名称来在运行时更改 IO 调度程序。例如,echo deadline > /sys/block/hda/queue/scheduler

于 2012-11-13T21:44:17.430 回答