Почему код/поток ядра, выполняющийся в контексте прерывания, не может спать?

Я хочу выбрать отдельные значения из одного столбца «GrondOfLucht», но они должны быть отсортированы в порядке, указанном в столбце «сортировка». Я не могу получить отличительные значения только одного столбца, используя

Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering

. Он также даст сортировку столбца, и, поскольку «GrondOfLucht» И «сортировка» не уникальны, результатом будут ВСЕ строки.

используйте GROUP, чтобы выбрать записи 'GrondOfLucht' в порядке, указанном в 'sorting

SELECT        GrondOfLucht
FROM            dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)
48
задан Methos 27 June 2009 в 20:41
поделиться

8 ответов

Я думаю, что это идея дизайна.

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


От Роберта Лав (хакер ядра): http://permalink.gmane.org/gmane.linux.kernel.kernelnewbies/1791

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

Это мало чем отличается от других операционных систем. В большинстве операционных систем прерывания не имеют потоков. Однако нижние половины часто бывают такими же.

Причина, по которой обработчик отказа страницы может "спать", заключается в том, что он вызывается только по коду, который выполняется в контексте процесса. Поскольку собственное ядро память не разбивается на страницы, только доступ к памяти пользовательского пространства может привести к ошибка страницы. Таким образом, только несколько определенных мест (например, звонки в copy_ {to, from} _user ()) может вызвать ошибку страницы в ядре. Те все места должны быть созданы с помощью кода, который может спать (т. е. контекст процесса, без замков и так далее).

30
ответ дан 26 November 2019 в 18:50
поделиться

Итак, что мешает планировщику поместить контекст прерывания переводить в спящий режим и переходить к следующему планируемому процессу и передавать ему управление?

Проблема в том, что контекст прерывания не является процессом и, следовательно, не может быть переведен в спящий режим.

Когда происходит прерывание, процессор сохраняет регистры в стеке и переходит к запуску процедуры обслуживания прерывания. Это означает, что когда обработчик прерывания работает, он выполняется в контексте процесса, который выполнялся, когда произошло прерывание. Прерывание выполняется в стеке этого процесса, и когда обработчик прерывания завершает работу, этот процесс возобновляет выполнение.

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

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

  1. Процесс1 входит в режим ядра.
  2. Процесс1 получает LockA ].
  3. Произошло прерывание.
  4. ISR начинает выполнение с использованием стека Process1 .
  5. ISR пытается получить LockA .
  6. ISR вызывает спящий режим, чтобы дождаться LockA будет освобожден.

На данный момент у вас тупик. Процесс1 может ' t возобновить выполнение, пока ISR не завершит работу со своим стеком. Но ISR заблокирована, ожидая, пока Process1 освободит LockA .

41
ответ дан 26 November 2019 в 18:50
поделиться

Так что же мешает планировщику перевести контекст прерывания в спящий режим и взять следующий планируемый процесс и передать ему управление?

Планирование происходит по прерываниям таймера. Основное правило состоит в том, что единовременно может быть открыто только одно прерывание, поэтому, если вы переходите в спящий режим в прерывании «Получены данные от устройства X», прерывание таймера не может запускаться для его выполнения.

Прерывания также происходят много раз. и перекрытие. Что произойдет, если вы переведете прерывание "получены данные" в спящий режим, а затем получите больше данных? Это достаточно сбивает с толку (и хрупко), что есть универсальное правило: не спать в прерываниях. Вы сделаете это неправильно.

3
ответ дан 26 November 2019 в 18:50
поделиться

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

Обычно ваша единственная цель в программе обработки прерывания - заставить устройство прекратить прерывание и поставить что-либо в очередь на более низком уровне прерывания (в unix обычно это уровень без прерывания, но для Windows это отправка, apc или пассивный уровень), чтобы выполнить тяжелую работу, где у вас есть доступ к большему количеству функций ядра / ОС. См. - Реализация обработчика .

Это свойство того, как должны работать операционные системы, а не что-то присущее Linux. Процедура прерывания может выполняться в любой момент, поэтому состояние того, что вы прервали, является несовместимым. Если вы прервали код планирования потоков, его состояние несовместимо, поэтому вы не можете быть уверены, что можете «спать» и переключать потоки. Даже если вы защищаете код переключения потоков от прерывания, переключение потоков - это функция очень высокого уровня ОС, и если вы защитили все, на что она опирается, прерывание становится скорее предложением, чем императивом, подразумеваемым его именем.

Это свойство того, как должны работать операционные системы, а не что-то присущее Linux. Процедура прерывания может выполняться в любой момент, поэтому состояние того, что вы прервали, является несовместимым. Если вы прервали код планирования потоков, его состояние несовместимо, поэтому вы не можете быть уверены, что можете «спать» и переключать потоки. Даже если вы защищаете код переключения потоков от прерывания, переключение потоков - это функция очень высокого уровня ОС, и если вы защитили все, на что она опирается, прерывание становится скорее предложением, чем императивом, подразумеваемым его именем.

Это свойство того, как должны работать операционные системы, а не что-то присущее Linux. Процедура прерывания может выполняться в любой момент, поэтому состояние того, что вы прервали, является несовместимым. Если вы прервали код планирования потоков, его состояние несовместимо, поэтому вы не можете быть уверены, что можете «спать» и переключать потоки. Даже если вы защищаете код переключения потоков от прерывания, переключение потоков - это функция очень высокого уровня ОС, и если вы защитили все, на что она опирается, прерывание становится скорее предложением, чем императивом, подразумеваемым его именем.

его состояние непоследовательно, поэтому вы не можете быть уверены, что можете «спать» и переключать потоки. Даже если вы защищаете код переключения потоков от прерывания, переключение потоков - это функция очень высокого уровня ОС, и если вы защитили все, на что она опирается, прерывание становится скорее предложением, чем императивом, подразумеваемым его именем.

его состояние непоследовательно, поэтому вы не можете быть уверены, что можете «спать» и переключать потоки. Даже если вы защищаете код переключения потоков от прерывания, переключение потоков - это функция очень высокого уровня ОС, и если вы защитили все, на что она опирается, прерывание становится скорее предложением, чем императивом, подразумеваемым его именем.

6
ответ дан 26 November 2019 в 18:50
поделиться

Даже если бы вы могли перевести ISR в спящий режим, вы бы не захотели этого делать. Вы хотите, чтобы ваши ISR были как можно быстрее, чтобы снизить риск пропуска последующих прерываний.

2
ответ дан 26 November 2019 в 18:50
поделиться

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

0
ответ дан 26 November 2019 в 18:50
поделиться

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

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

0
ответ дан 26 November 2019 в 18:50
поделиться

Ядро linux имеет два способа выделения стека прерываний. Первый - на стеке ядра прерванного процесса, второй - выделенный стек прерываний для каждого процессора. Если контекст прерывания сохраняется в выделенном стеке прерываний для каждого процессора, то действительно контекст прерывания совершенно не связан ни с каким процессом. Макрос "current" будет выдавать недействительный указатель на текущий запущенный процесс, так как макрос "current" в некоторых архитектурах вычисляется с указателем стека. Указатель стека в контексте прерывания может указывать на выделенный стек прерывания, а не на стек ядра какого-либо процесса.

0
ответ дан 26 November 2019 в 18:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: