Linux中IO调度器按块设备独立配置,必须用cat /sys/block/设备名/queue/scheduler查看,方括号内为当前生效项;NVMe设备默认[none]属正常,不可强行修改,SATA SSD推荐mq-deadline或kyber,HDD适用mq-deadline。

cat /sys/block/设备名/queue/scheduler 看当前激活项
Linux 没有全局“系统级”IO调度策略,每个块设备(如 sda、nvme0n1)独立配置,必须指定设备名才能查真实状态。直接运行 cat /sys/block/sda/queue/scheduler(把 sda 换成你的目标设备)即可。输出形如 [mq-deadline] kyber bfq none,方括号里那个就是当前实时生效的调度器。
常见误区:
- 用
lsblk或df查——这些命令不暴露调度器信息 - 查
/proc/sys/kernel/sched_*——那是 CPU 调度参数,和 IO 无关 - 对
sr0(光驱)、loop、zram设备执行该命令——它们不是物理块设备,返回可能无意义或报错
确认设备名最稳妥的方式是:lsblk -d(只显示磁盘,不带分区),排除 md、dm- 等逻辑设备;或者 cat /proc/partitions | grep -E '^[a-z]+',挑出首列为字母的行。
看到 [none] 就别硬改,尤其 NVMe 设备
NVMe 设备(如 nvme0n1)在较新内核中默认显示 [none],这不是错误,而是内核主动绕过软件调度层,交由硬件队列直接处理。此时向 /sys/block/nvme0n1/queue/scheduler 写入任何值(比如 echo kyber)都会失败或被忽略,cat 后仍显示 [none]。
判断依据:
-
lspci | grep -i nvme确认是 NVMe 控制器 - 输出含
none且其他选项(如kyber)也在列表里——说明支持但未启用,[none]是主动选择 - SATA SSD 却显示
[cfq]或[deadline]——才值得考虑切换
强行写入不仅无效,还可能触发内核日志警告:write to scheduler failed: Invalid argument。
临时修改后怎么验证是否真生效
写入成功不等于调度器立刻按新逻辑工作——得看后续 I/O 行为是否变化。不能只信 cat 输出方括号移位,要结合 iostat -x 1 观察实际效果:
- 改完立即跑
iostat -xk 1 /dev/sda(替换为对应设备),盯await和avgqu-sz:若从高延迟、长队列变成低延迟、短队列,说明调度器起效了 - 对 HDD 改用
mq-deadline后,r_await应明显下降(尤其小随机读场景) - 对 SATA SSD 改用
kyber后,avgqu-sz若长期 > 1 且await上升,反而说明调度器引入了额外开销,应回退 - 如果
%util依然接近 100%,但await和avgqu-sz都很低——瓶颈不在调度器,可能是磁盘本身或上层应用(如数据库锁、日志刷盘策略)
注意:echo mq-deadline > /sys/block/sda/queue/scheduler 必须用 root 权限,且只能写入 cat 输出中列出的选项,写错会报 Invalid argument。
为什么改了却没生效?三个最常漏掉的点
临时修改看似简单,但实际卡住的地方往往很隐蔽:
-
设备名动态变化:重启后
sda可能变sdb,尤其插拔过 USB 盘或 RAID 重构过。用ls -l /dev/disk/by-path/找稳定路径,再映射到sysfs下对应设备(如pci-0000:00:1f.2-ata-1→ata1→host0→target0:0:0→block:sda) -
调度器不支持 ionice:改完
mq-deadline,再用ionice -p PID查进程优先级,若返回none,说明该调度器不参与 I/O 优先级调度,ionice设置无效 -
内核模块未加载:某些定制内核把
kyber编译成模块而非内置,cat /sys/block/sda/queue/scheduler不显示它,需先modprobe kyber-iosched才能写入
真正稳定的永久方案不是靠 GRUB 参数一刀切,而是用 udev 规则绑定设备路径+调度器,避免重启后设备名漂移导致失效。


















