Linux中每个块设备独立配置IO调度器,需通过/sys/block/设备名/queue/scheduler查看和修改;NVMe设备默认[none]无需更改,SATA SSD推荐mq-deadline或kyber,HDD适用mq-deadline;临时修改用echo写入sysfs,永久生效需添加elevator=参数至GRUB并更新配置。

Linux 中没有全局“系统级”的 IO 调度算法,每个块设备(如 sda、nvme0n1)独立配置调度器,必须按设备查、按设备改。
查看当前设备的 IO 调度器
调度器信息不通过 lsblk 或 df 暴露,只存在于 /sys 接口里。路径固定为 /sys/block/设备名/queue/scheduler:
- 先确认设备名:
lsblk -d或cat /proc/partitions,排除loop、dm-、zram等非物理设备 - 查
sda的调度器:cat /sys/block/sda/queue/scheduler,输出形如noop [deadline] mq-deadline kyber,方括号内是当前激活项 - NVMe 设备(如
nvme0n1)常显示[none]—— 这不是错误,而是内核主动绕过软件调度层,此时写入任何调度器名都会失败或被忽略 - 若看到
none且你确信是 NVMe,不用强行改;若 SATA SSD 显示[cfq],才值得考虑切换
临时切换调度器(重启失效)
这个操作立即生效,适合快速验证效果,但对根设备(如装系统的 sda)慎用,可能引发短暂卡顿:
- 必须用 root 权限:
sudo sh -c 'echo deadline > /sys/block/sda/queue/scheduler' - 只能写入
cat输出中列出的选项(比如不能写cfq到只显示noop mq-deadline的设备上) - 写错会报
Invalid argument;写成功后再次cat应看到方括号移位 - 部分 RAID 卡或旧驱动不支持
mq-deadline,写入后仍显示原值,说明内核拒绝了该设置
永久修改 IO 调度器
靠内核启动参数 elevator=xxx 实现,不是改配置文件,也不是 systemd 服务:
- 编辑
/etc/default/grub,在GRUB_CMDLINE_LINUX_DEFAULT行末加空格分隔的参数,例如:elevator=mq-deadline - 执行
sudo update-grub(Debian/Ubuntu)或sudo grub2-mkconfig -o /boot/grub2/grub.cfg(RHEL/CentOS) - 重启后才生效;若启动失败,进 GRUB 编辑启动项,临时删掉
elevator=参数可恢复 - 注意:该参数统一作用于所有块设备,无法为 SSD 和 HDD 分别指定;若混用介质,建议改用 udev 规则更精准
Noop、Deadline、mq-deadline 怎么选?
选错不仅没收益,还可能增加延迟。关键看设备类型和 IO 特征:
-
noop:纯 FIFO,零逻辑开销。适合 NVMe(固件已优化)、云盘(如 AWS EBS、阿里云云盘)、容器镜像层 —— 这些场景内核调度反而成累赘 -
deadline:旧内核( -
mq-deadline:5.0+ 内核默认,专为多队列块层(blk-mq)设计,逻辑同deadline但更高效。HDD、RAID 卡、虚拟机磁盘推荐 - CFQ/BFQ 已基本淘汰,新内核默认不用;HDD 上硬套
noop可能导致大量随机 IO 延迟飙升,别跟风
最容易被忽略的一点:很多现代 NVMe 驱动直接返回 [none],这不是 bug,是设计使然。此时任何写入 /sys/block/nvme0n1/queue/scheduler 的尝试都无效,也不该尝试 —— 强行覆盖反而可能触发内核警告或降级到兼容模式。


















