Что делает программа, когда посылает сигнал SIGKILL?

39

Когда я использовал, killall -9 nameчтобы убить программу, государство стало зомби. Через несколько минут это действительно прекратилось. Итак, что происходит в эти минуты?

хайкун хе
источник

Ответы:

66

Программа фактически никогда не получает сигнал SIGKILL, поскольку SIGKILL полностью обрабатывается операционной системой / ядром.

Когда отправляется SIGKILL для определенного процесса, планировщик ядра немедленно прекращает предоставлять этому процессу больше процессорного времени для выполнения кода пользовательского пространства. Если у процесса есть какие-либо потоки, выполняющие код пользовательского пространства на других процессорах / ядрах в то время, когда планировщик принимает это решение, эти потоки также будут остановлены. (В одноядерных системах это было намного проще: если планировщик работал только на одном ядре ЦП в системе, он по определению не запускал процесс одновременно!)

Если процесс / поток выполняет код ядра (например, системный вызов или операцию ввода-вывода, связанную с отображенным в память файлом) во время SIGKILL, он становится немного хитрее: только некоторые системные вызовы прерываются, поэтому Ядро внутренне помечает процесс как находящийся в специальном «умирающем» состоянии, пока системные вызовы или операции ввода-вывода не будут разрешены. Время процессора для их решения будет запланировано как обычно. Прерываемые системные вызовы или операции ввода / вывода проверят, умирает ли вызывающий их процесс в любых подходящих точках остановки, и в этом случае завершатся досрочно. Непрерывные операции будут выполняться до конца и будут проверять состояние «умирания» непосредственно перед возвратом к коду пользовательского пространства.

Как только все внутрипроцессные подпрограммы ядра разрешены, состояние процесса изменяется с «умирающего» на «мертвое», и ядро ​​начинает его очищать, подобно тому, как обычно программа завершается. Как только очистка будет завершена, будет назначен код результата, превышающий 128 (чтобы указать, что процесс был прерван сигналом; подробности см. В этом ответе ), и процесс перейдет в состояние «зомби» , Родитель убитого процесса будет уведомлен с сигналом SIGCHLD.

В результате сам процесс никогда не получит возможности фактически обработать информацию, которую он получил SIGKILL.

Когда процесс находится в состоянии «зомби», это означает, что процесс уже мертв, но его родительский процесс еще не подтвердил это, прочитав код завершения мертвого процесса с помощью wait(2)системного вызова. По сути, единственный ресурс, который зомби-процесс потребляет больше - это слот в таблице процессов, в котором хранятся его PID, код выхода и некоторая другая «важная статистика» процесса в момент его смерти.

Если родительский процесс умирает раньше своих потомков, осиротевшие дочерние процессы автоматически принимаются PID # 1, у которого есть особая обязанность продолжать вызывать вызовы, wait(2)чтобы любые осиротевшие процессы не оставались зомби.

Если процесс очистки зомби занимает несколько минут, это говорит о том, что родительский процесс зомби испытывает трудности или не выполняет свою работу должным образом.

Существует насмешливое описание того, что делать в случае проблем с зомби в Unix-подобных операционных системах: «Вы ничего не можете сделать для самих зомби, так как они уже мертвы. Вместо этого убейте злого мастера зомби! » (т.е. родительский процесс проблемных зомби)

Телком
источник
5
Что произойдет, если процесс находится в вызове ядра (например, выполняет ввод-вывод) при отправке SIGKILL?
Gidds
9
@gidds Либо ввод-вывод будет отменен для выполнения SIGKILL, либо SIGKILL будет задержан до завершения ввода-вывода. В этом заключается разница между состояниями сна 'S' и 'D' в ps: 'S' - это ожидания ввода-вывода, которые ядро ​​может отменить для доставки сигнала, и 'D' для тех, которые не могут.
Звол
6
Не совсем точно сказать, что расписание сразу перестает давать процессорное время процесса. Ядро обработки сигналов по-прежнему выполняется этим процессом, но процесс будет выполнять только код ядра, поэтому вы правы, когда говорите, что программа никогда не получает сигнал. Процесс будет выполнять код ядра, отвечающий за большую часть очистки ресурсов (открытых файлов, виртуальной памяти и т. Д.). Последние шаги этого кода очистки состоят в том, чтобы изменить состояние процесса на «зомби» и вызвать планировщик. Тогда это никогда не будет запланировано снова.
Касперд
4
@gidds Существует как минимум четыре разных состояния, в которых может находиться процесс. В данный момент он может выполнять код ядра или находиться в спящем состоянии в одном из трех разных состояний сна. Спящие состояния могут быть прерывистыми, непрерывными или непрерывными, за исключением смертельных сигналов. Если он находится в непрерывном сне, его оставляют спать столько, сколько ему нужно, и только после пробуждения у него будет шанс умереть. Если он находился в одном из двух других спящих состояний, он будет сразу же активирован и запланирован, как только для него будет доступен процессор.
Касперд
2
@gidds Что будет дальше, зависит от кода ядра, на котором он работал. Независимо от того, был ли он уже запущен или его сначала нужно было разбудить, а затем можно было запустить код ядра, в котором он находился в то время, будет разрешено продолжить работу. И этот код ядра отвечает за то, что процессу было приказано умереть и действовать соответственно. В большинстве случаев правильный способ справиться с этим в коде ядра - просто вернуть ошибку из любой функции, которую он выполнял. Как только стек вызовов ядра был размотан, код обработки сигналов может вступить во владение непосредственно перед возвратом в режим пользователя.
Касперд