Процесс в состоянии D игнорирует kill -9 — почему и что делать
Задача бэкапа зависла и не умирает. Вы пытаетесь её убить, а она остаётся. Ниже — что показывает машина. Объясните, в каком состоянии процесс, почему SIGKILL не действует и что с этим реально можно сделать.
$ ps -eo pid,ppid,stat,wchan,cmd | grep 4712
4712 1 D+ rwsem_down_read dd if=/dev/sdb of=/backup/img bs=4M
$ sudo kill -9 4712
$ ps -o pid,stat,cmd 4712
4712 D+ dd if=/dev/sdb of=/backup/img bs=4M # всё ещё здесь после SIGKILL
$ grep State /proc/4712/status
State: D (disk sleep)
Определите состояние и дайте ответ.
D — это непрерываемый сон: процесс заблокирован внутри ядерного вызова — здесь dd ждёт отказывающий диск. SIGKILL ставится в очередь, но не доставляется, пока вызов не вернётся, поэтому kill -9 бездействует, пока он висит. Убить силой нельзя; почините ввод-вывод (больное устройство, NFS, хранилище), чтобы вызов разблокировался и процесс вышел — иначе перезагрузка хоста.
- ✗Упорнее слать
kill -9, когда процесс вDпока не может его получить - ✗Принимать непрерываемый сон за зомби или перехват сигнала обработчиком
- ✗Игнорировать настоящую причину — застрявший диск, NFS или ввод-вывод устройства
- →Как определить, на каком устройстве или монтировании процесс заблокирован?
- →Почему ядро вообще использует непрерываемый сон для части ввода-вывода?
Решение
1. Прочитать состояние
Колонка STAT показывает D+ — непрерываемый сон (D (disk sleep) в /proc/4712/status). Поле wchan = rwsem_down_read говорит, что процесс спит в ядре, ожидая блокировку/ввод-вывод. dd if=/dev/sdb читает больное устройство.
2. Почему kill -9 бессилен
$ sudo kill -9 4712 # сигнал поставлен в очередь…
$ grep State /proc/4712/status
State: D (disk sleep) # …но не доставлен: процесс всё ещё в D
SIGKILL доставляется только когда процесс выходит из ядра в пользовательский режим. Пока он висит в непрерываемом сне внутри системного вызова, сигнал не обрабатывается — даже kill -9 ждёт. Это не зомби и не перехват сигнала: убить его сейчас нельзя.
3. Что реально делать
Устраните причину ввода-вывода: проверьте dmesg на ошибки /dev/sdb, зависшую NFS-точку или сбойный контроллер. Когда вызов разблокируется (вернётся или отвалится по таймауту), поставленный в очередь SIGKILL доставится и процесс умрёт. Если устройство мертво навсегда — остаётся перезагрузка хоста.