[kthreadd]和[kswapd0]本身不会长期处于D状态:前者仅管理线程、几乎不阻塞;后者D态仅瞬时等待I/O,若持久化则表明底层存储、文件系统或块设备层异常,需结合stack、dmesg、iostat等定位真实阻塞点。
![进程 d 状态卡在 [kthreadd] 或 [kswapd0] 的深层原因定位](https://img.php.cn/upload/article/001/242/473/176886416294115.jpeg)
进程显示为 D 状态(不可中断睡眠),且名字是 [kthreadd] 或 [kswapd0],这本身是个误解或误读——因为这两个是内核线程,它们永远不会以 D 状态长期卡住,也不会“卡在自己身上”。真正的问题是:你看到的 D 状态进程,很可能不是它们本身,而是其他进程被阻塞在等待它们所服务的底层资源上;或者你用工具(如 ps)误把内核线程状态和其调用栈混淆了。
为什么 [kthreadd] 不可能“卡在 D 状态”
[kthreadd] 是内核线程管理器(kernel thread daemon),只负责创建/回收其他内核线程,它自身几乎不执行 I/O、不持有锁、不等待设备。它的状态通常是 S(可中断睡眠)或 R(运行),不会处于 D 状态。如果你在 ps 或 top 中看到它标为 D,大概率是:
- 工具解析 /proc/PID/stat 出错(尤其在旧内核或容器中)
- 你实际看到的是某个子线程(如
[kworker/u8:3+events_unbound])被阻塞,但列名被截断或显示异常 - 系统已严重僵死,/proc 文件系统无法及时更新,状态字段失效
[kswapd0] 显示 D 的真实含义
[kswapd0] 是内核内存回收线程,它在内存压力大时主动唤醒,执行页回收(reclaim)、换出(swap out)等操作。它进入 D 状态仅发生在极短时间内等待 I/O 完成(例如写脏页到 swap 分区或块设备)。如果它长时间显示为 D,说明:
- 后端存储(如 swap 分区所在的磁盘、LVM 设备、NVMe 队列)出现响应延迟或 hang
- 文件系统层(如 XFS 日志阻塞、ext4 journal wait)拖住了页回收路径
- 存在 I/O 调度器死锁或 blk-mq 队列卡死(常见于 misconfigured multi-queue NVMe 或驱动 bug)
此时,kswapd0 本身没卡,而是它发起的 bio 请求在 block 层无限等待完成。需检查 /proc/diskstats、dmesg -T | grep -i "block\|io\|nvme\|ata" 和 iostat -x 1 是否有 %util=100、await 异常升高、r/s w/s 为 0 但队列堆积。
如何准确定位真正的阻塞源头
D 状态进程的根因永远不在它自己,而在它等待的资源。定位步骤如下:
- 用
cat /proc/查看该进程内核态调用栈(需 CONFIG_STACKTRACE=y),重点关注末尾函数:若含/stack wait_event_*、__lock_down、blk_mq_wait_dispatch、submit_bio_wait,说明卡在 I/O 或锁 - 用
crash(若有 kdump)分析所有 D 进程的 wait_channel,比对是否共用同一等待队列(如swapper_space、sb_writers) - 检查
/sys/block/和/device/state /sys/block/判断设备是否 offline 或 queue hung/queue/delayed - 运行
lsof +D /(慎用)或find /proc/[0-9]*/fd -ls 2>/dev/null | grep deleted排查是否有进程持有着已被删除但仍打开的大文件(导致 page cache 回收受阻)
典型场景与快速验证点
常见组合模式:
- D 进程 + kswapd0 同时高 CPU 或 D → 检查 swap 分区是否在慢盘上(如 USB 盘)、swapiness 是否过高(>100)、是否有大量匿名页待换出
-
多个 D 进程堆叠,stack 都停在 xfsaild 或 xlog_wait → XFS 日志满或 log device hang,运行
xfs_info /mountpoint和xfs_logprint /dev/sdX - D 进程 stack 含 nfs_update_inode / __nfs_wait_on_request → NFS server 响应超时或防火墙拦截了 callback port
- D 进程 + dmesg 报 “INFO: task XXX blocked for more than 120 seconds” → 内核已触发 hung_task detector,查看完整 trace,重点看 lockdep 输出








