2008-10-21 4 views
121

Иногда, когда я пишу программу в Linux, и она выходит из строя из-за какой-то ошибки, она станет непрерывным процессом и продолжает работать вечно до тех пор, пока я не перезапущу свой компьютер (даже если я выйду из системы). Мои вопросы:Что такое непрерывный процесс?

  • Что заставляет процесс стать бесперебойным?
  • Как остановить это?
  • Это, наверное, немой вопрос, но есть ли способ прервать его без перезагрузки моего компьютера?
+0

, пожалуйста, поделитесь этим кодом? – again 2018-02-20 09:29:29

ответ

155

Непрерывный процесс - это процесс, который происходит в системном вызове (функция ядра), который не может быть прерван сигналом.

Чтобы понять, что это значит, вам необходимо понять концепцию прерывания системного вызова. Классический пример - read(). Это системный вызов, который может занять много времени (в секундах), поскольку он может потенциально включать разворот жесткого диска или перемещение головок. В течение большей части этого времени процесс будет спать, блокируя оборудование.

Пока процесс спит в системном вызове, он может получить асинхронный сигнал UNIX (скажем, SIGTERM), то происходит следующее:

  • система вызывает выходы преждевременно, и настроен вернуть -EINTR в пользовательское пространство.
  • Обработчик сигналов выполнен.
  • Если процесс все еще запущен, он получает возвращаемое значение из системного вызова и повторяет тот же вызов.

Возврат раннего из системного вызова позволяет код пространства пользователя немедленно изменять его поведение в ответ на сигнал. Например, чистое завершение реакции на SIGINT или SIGTERM.

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

LWN пробежал nice article, который коснулся этой темы в июле.

Чтобы ответить на исходный вопрос:

  • Как предотвратить это: выяснить, какой драйвер вызывает вам неприятности, и либо прекратить использование или стать ядром хакера и исправить ее.

  • Как убить бесперебойный процесс без перезагрузки: каким-то образом завершить системный вызов. Часто самый эффективный способ сделать это, не нажав на выключатель питания, - это вытянуть шнур питания. Вы также можете стать хакером ядра и заставить драйвер использовать TASK_KILLABLE, как описано в статье LWN.

+46

+1 для `наиболее эффективного способа сделать это, не нажав на выключатель питания, - это вытащить рычаг питания – daisy 2012-09-28 09:34:04

+20

@ warl0ck: [Сила аккорда] (https://en.wikipedia.org/wiki/Power_chord)? – 2013-07-16 22:01:35

-2

Не могли бы вы описать, что такое «непрерывный процесс»? Выживает ли он «убить -9» и счастливо болтает? Если это так, то он застрял на каком-то системном компьютере, который застрял в каком-то драйвере, и вы застряли в этом процессе до перезагрузки (а иногда и лучше перезагрузить) или разгрузки соответствующего драйвера (что вряд ли произойдет) , Вы можете попытаться использовать «strace», чтобы узнать, где ваш процесс застрял и избежать его в будущем.

Но если вы говорите о процессе «зомби» (который обозначается как «зомби» в выводе ps), то это безобидная запись в списке процессов, ожидающая, когда кто-то соберет код возврата, и это может быть безопасно игнорируется.

+0

Прочтите ответы выше – 2013-09-23 14:48:05

+0

Нельзя ли принудительно ** выгрузить ** так же, как может быть убит процесс? Я знаю, что режим ядра имеет более привилегированный доступ, чем пользовательский режим, но никогда не может быть более привилегированным, чем сама операционная система. Все, что выполняется в режиме ядра, всегда может вмешиваться в что-либо другое, выполняемое в режиме ядра - просто нет контроля. – Dexter 2015-11-24 14:47:27

36

Когда процесс находится в пользовательском режиме, его можно прервать в любое время (переход в режим ядра). Когда ядро ​​возвращается в пользовательский режим, он проверяет наличие ожидающих сигналов (включая те, которые используются для уничтожения процесса, такие как SIGTERM и SIGKILL). Это означает, что процесс может быть убит только при возврате в пользовательский режим.

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

Когда ядро ​​должно выполнить что-то, что может занять много времени (ожидание на трубке, написанном другим процессом или ожидающее, когда аппаратное обеспечение что-то сделает, например), он спит, отмечая себя как спящий и вызывающий планировщик для переключения на другой процесс (если нет процесса без сна, он переключается на «фиктивный» процесс, который сообщает процессору замедлить бит и сидит в цикле — цикл простоя).

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

  • TASK_INTERRUPTIBLE, прерывистый сон. Если задача отмечена этим флагом, она спит, но может быть разбужена сигналами. Это означает, что код, обозначающий задачу как спящий, ожидает возможного сигнала, и после того, как он просыпается, он проверит его и вернется с системного вызова. После обработки сигнала системный вызов может быть автоматически перезапущен (и я не буду вдаваться в подробности о том, как это работает).
  • TASK_UNINTERRUPTIBLE, бесперебойный сон. Если задача отмечена этим флагом, она не ожидает, что ее разбудят что-либо, кроме того, что она ожидает, либо потому, что ее невозможно перезапустить, либо потому, что программы ожидают, что системный вызов будет атомарным. Это также можно использовать для сон, которые, как известно, очень короткие.

TASK_KILLABLE (упоминается в статье LWN, связанной с ответом ddaa) - это новый вариант.

Это отвечает на ваш первый вопрос. Что касается вашего второго вопроса: вы не можете избежать бесцельных сна, это обычная вещь (это происходит, например, каждый раз, когда процесс читает/записывает с/на диск); однако они должны длиться всего лишь часть секунды. Если они длится намного дольше, обычно это означает аппаратную проблему (или проблему с драйвером устройства, которая аналогична ядру), когда драйвер устройства ожидает, что аппаратное обеспечение сделает что-то, чего никогда не произойдет. Это также означает, что вы используете NFS, а сервер NFS недоступен (он ждет восстановления сервера, вы также можете использовать опцию «intr», чтобы избежать проблемы).

И наконец, причина, по которой вы не можете восстановить, по той же причине, что ядро ​​ждет, пока не вернется в пользовательский режим, чтобы доставить сигнал или убить процесс: это потенциально повредило бы структуры данных ядра (код, ожидающий прерывания сна, может получить ошибка, которая говорит ему вернуться в пространство пользователя, где процесс может быть убит, ожидающий в режиме бесперебойного сна ожидания код не ожидает никакой ошибки).

17

Бесперебойные процессы в USUALLY ждут ввода/вывода после сбоя страницы.

Рассмотрим это:

  • Нить пытается получить доступ к странице, которая не находится в ядре (или исполняемый файл, который загружены по требованию, страница анонимной памяти, которая была выгружена или ММАП (), который загружен по требованию, что почти то же самое)
  • Ядро сейчас (пытается загрузить) в
  • Процесс не может продолжаться до тех пор, пока страница не будет доступна.

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

Когда я говорю «процесс», я на самом деле означает «задачу», которая под Linux (2,6) примерно переводится на «поток», который может или не может иметь запись отдельного «нить группы» в/Proc

В некоторых случаях это может длиться долго. Типичным примером этого будет то, что исполняемый файл или файл mmap'd находятся в сетевой файловой системе, где сервер потерпел неудачу. Если сбой ввода-вывода будет завершен, задача будет продолжена. Если это в конечном итоге не удастся, задача, как правило, получит SIGBUS или что-то еще.

2

Возможно ли, что программа может быть записана для инициирования процесса, который переходит в состояние TASK_UNINTERUPTIBLE всякий раз, когда система не находится в состоянии ожидания, тем самым принудительно собирает данные, ожидая передачи после выхода суперпользователя? Это было бы золотым моментом для хакеров для получения информации, возврата в состояние зомби и передачи информации через сеть на холостом ходу. Некоторые могут утверждать, что это один из способов создания Blackdoor для полномочий, которые должны быть, для входа и выхода из любой системы по желанию. Я твердо верю, что эта лазейка может быть запечатана навсегда, устраняя состояние TASK_UNINTERUPTIBLE.

Я рассматриваю это как серьезную, но тонкую проблему безопасности для Linux-систем, которые имеют репутацию безопасности, благодаря расширению прав и возможностей суперпользователя. Тем не менее, я работаю над тем, чтобы стать хакером. Я думаю, что есть хакеры ядра, которые могут исправить этот фиаско.

0

На ваш третий вопрос: Я думаю, вы можете убить непрерывные процессы, запустив sudo kill -HUP 1. Он перезапустит init, не закончив запущенные процессы, и после его запуска мои непрерывные процессы исчезли.