Что такое непрерывный процесс?
иногда, когда я пишу программу в Linux, и она падает из-за какой-то ошибки, она станет непрерывным процессом и будет продолжать работать вечно, пока я не перезагружу компьютер (даже если я выйду из системы). Мои вопросы:
- что заставляет процесс становиться непрерывным?
- как мне остановить это?
- Это, вероятно, глупый вопрос, но есть ли способ прервать его без перезапуска моего компьютер?
6 ответов:
непрерывный процесс-это процесс, который находится в системном вызове (функция ядра), который не может быть прерван сигналом.
чтобы понять, что это значит, вам нужно понять концепцию прерываемого системного вызова. Классический пример
read(). Это системный вызов, который может занять много времени (секунд), так как он потенциально может включать в себя вращение жесткого диска или перемещение головок. В течение большей части этого времени процесс будет спать, блокируя аппаратура.пока процесс спит в системном вызове, он может получить асинхронный сигнал unix (скажем, SIGTERM), тогда происходит следующее:
- системные вызовы завершаются преждевременно и настраиваются на возврат-EINTR в пользовательское пространство.
- обработчик сигнала выполняется.
- если процесс все еще выполняется, он получает возвращаемое значение от системного вызова, и он может сделать тот же вызов снова.
возвращаясь рано от системного вызова позволяет коду пространства пользователя немедленно изменить свое поведение в ответ на сигнал. Например, завершение чисто в реакции на SIGINT или SIGTERM.
С другой стороны, некоторые системные вызовы не могут быть прерваны таким образом. Если система по какой-то причине вызывает stalls, процесс может бесконечно оставаться в этом неубиваемом состоянии.
LWN ran a хорошая статья это коснулось этой темы в июле.
To ответьте на исходный вопрос:
Как предотвратить это: выясните, какой драйвер вызывает у вас проблемы, и либо прекратите использовать, либо станьте хакером ядра и исправьте его.
Как убить бесперебойный процесс без перезагрузки: как сделать системный вызов завершить. Часто наиболее эффективным способом сделать это, не нажимая на выключатель питания, является вытянуть шнур питания. Вы также можете стать хакером ядра и сделать драйвер использует TASK_KILLABLE, как описано в статье LWN.
когда процесс находится в пользовательском режиме, он может быть прерван в любое время (переключение в режим ядра). Когда ядро возвращается в пользовательский режим, оно проверяет, есть ли какие-либо сигналы в ожидании (включая те, которые используются для уничтожения процесса, такие как
SIGTERMиSIGKILL). Это означает, что процесс может быть убит только при возвращении в пользовательский режим.причина, по которой процесс не может быть убит в режиме ядра, заключается в том, что он может потенциально повредить структуры ядра, используемые всеми другими процессами в той же машине (таким же образом убийство потока может потенциально повредить структуры данных, используемые другими потоками в том же процессе).
когда ядру нужно сделать что-то, что может занять много времени (ожидание на канале, написанном другим процессом или ожидание аппаратного обеспечения, чтобы сделать что-то, например), он спит, помечая себя как спящий и вызывая планировщик для переключения на другой процесс (если нет не спящего процесса, он переключается на "фиктивный" процесс, который говорит процессору немного замедлиться и сидит в цикле - цикл простоя).
если сигнал отправляется в спящий процесс, он должен быть разбужен, прежде чем он вернется в пространство пользователя и, таким образом, обработает ожидающий сигнал. Здесь мы имеем разницу между двумя основными типами сна:
TASK_INTERRUPTIBLE, прерываемый сон. Если задача отмечена этим флагом, она спит, но может быть разбужена сигналами. Это означает, что код, который пометил задачу как спящий, является ожидая возможного сигнала, и после того, как он проснется, проверит его и вернется из системного вызова. После обработки сигнала системный вызов может быть автоматически перезапущен (и я не буду вдаваться в подробности о том, как это работает).TASK_UNINTERRUPTIBLE, источник бесперебойного сна. Если задача отмечена этим флагом, она не ожидает пробуждения от чего-либо другого, кроме того, что она ожидает, либо потому, что она не может быть легко перезапущена, либо потому, что программы ожидают системный вызов должен быть атомарным. Это также может быть использовано для сна, который, как известно, очень короткий.
TASK_KILLABLE(упоминается в статье LWN, связанной с ответом ddaa) - это новый вариант.Это ответ на ваш первый вопрос. Что касается вашего второго вопроса: Вы не можете избежать непрерывных снов, они являются нормальной вещью (это происходит, например, каждый раз, когда процесс читает/записывает с/на диск); однако они должны длиться только долю секунды. Если они длятся много более того, это обычно означает аппаратную проблему (или проблему с драйвером устройства, которая выглядит одинаково для ядра), где драйвер устройства ожидает, что оборудование сделает что-то, что никогда не произойдет. Это также может означать, что вы используете NFS, и сервер NFS не работает (он ждет восстановления сервера; вы также можете использовать опцию "intr", чтобы избежать проблемы).
наконец, причина, по которой вы не можете восстановить, - это та же причина, по которой ядро ждет возвращения в пользовательский режим для доставки сигнализируйте или убейте процесс: это потенциально повредит структуры данных ядра (код, ожидающий прерываемого сна, может получить ошибку, которая говорит ему вернуться в пользовательское пространство, где процесс может быть убит; код, ожидающий бесперебойного сна, не ожидает никакой ошибки).
непрерывные процессы обычно ожидают ввода-вывода после ошибки страницы.
рассмотрим следующий пример:
- поток пытается получить доступ к странице, которая не находится в ядре (либо исполняемый файл, который загружен по требованию, страница анонимной памяти, которая была заменена, или файл mmap () ' D, который загружен по требованию, что почти одно и то же)
- ядро теперь (пытается) загрузить его в
- процесс не может продолжаться до тех пор, пока страница доступный.
процесс / задача не может быть прерван в этом состоянии, потому что он не может обрабатывать какие-либо сигналы; если бы это произошло, произошла бы другая ошибка страницы, и она вернулась бы туда, где она была.
когда я говорю "процесс", я действительно имею в виду" задачу", которая под Linux (2.6) примерно переводится как" поток", который может иметь или не иметь отдельную запись" группа потоков " в /proc
в некоторых случаях, он может ждать долго. Типичным примером этого может быть где исполняемый файл или mmap'D находится в сетевой файловой системе, где произошел сбой сервера. Если ввод-вывод в конечном итоге завершится успешно, задача будет продолжена. Если это в конечном итоге не удастся, задача, как правило, получит SIGBUS или что-то в этом роде.
возможно ли, что программа может быть написана, чтобы инициировать процесс, который идет в
TASK_UNINTERUPTIBLEсостояние всякий раз, когда система не находится в состоянии ожидания, тем самым принудительно собирая данные, ожидая передачи после выхода суперпользователя? Это будет золотая жила для хакеров, чтобы получить информацию, вернуться в состояние зомби, и передавать информацию через сеть на холостом ходу. Некоторые могут утверждать, что это один из способов созданияBlackdoorдля сильных мира сего, чтобы войти и выйти из любой системы, как желанный. Я твердо верю, что эта лазейка может быть запечатана навсегда, устранивTASK_UNINTERUPTIBLEгосударство.Я рассматриваю это как серьезную, но тонкую проблему безопасности для систем Linux, которые имеют репутацию безопасности, благодаря расширению прав и возможностей суперпользователя. Я работаю над тем, чтобы стать хакером ядра, однако, я думаю, что есть хакеры ядра, которые могут исправить это фиаско.
к вашему 3-му вопросу: Я думаю, что вы можете убить бесперебойные процессы, запустив
sudo kill -HUP 1. Он перезапустит init без завершения запущенных процессов, и после его запуска мои непрерывные процессы исчезли.
Если вы говорите о процессе" зомби "(который обозначается как" зомби " в выводе ps), то это безвредная запись в списке процессов, ожидающая кого-то, чтобы собрать свой код возврата, и ее можно было бы безопасно игнорировать.
не могли бы вы описать, что такое "непрерывный процесс" для вас? Выживает ли он "убить -9" и счастливо пыхтит вместе? Если это так, то он застрял на каком-то syscall, который застрял в каком-то драйвере, и вы застряли с этим процесс до перезагрузки (а иногда лучше перезагрузиться в ближайшее время) или выгрузки соответствующего драйвера (что вряд ли произойдет). Вы можете попробовать использовать "strace", чтобы узнать, где ваш процесс застрял и избежать его в будущем.
Comments