Что такое непрерывный процесс? - PullRequest
136 голосов
/ 22 октября 2008

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

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

Ответы [ 5 ]

172 голосов
/ 22 октября 2008

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

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

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

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

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

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

LWN опубликовал хорошую статью , которая затрагивала эту тему в июле.

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

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

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

42 голосов
/ 22 октября 2008

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

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

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

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

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

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

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

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

20 голосов
/ 23 октября 2008

Непрерывные процессы обычно ожидают ввода-вывода после ошибки страницы.

Учтите это:

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

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

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

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

0 голосов
/ 28 мая 2017

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

0 голосов
/ 22 октября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...