Теория от Рязановой к лр1 - chrislvt/OS GitHub Wiki

ТЕОРИЯ К ЛР1

ЧАСТЬ 1

Дизассемблирование INT 8h

В процессорах Intel, микроконтроллерах AVR и некоторых других существуют отдельные команды для ввода-вывода — IN и OUT — и, соответственно, отдельное адресное пространство: в процессорах Intel — от 0000 (в шестнадцатричной сс) до FFFF (в шестнадцатиричной сс).

Таблица векторов прерываний располагается в памяти начиная с нулевого адреса. Каждый вектор занимает в таблице 4 байта: 2 байта сегмент и 2 байта смещение ( far адрес ).

image

Для получения адреса вектора из таблицы векторов прерываний необходимо:

  • Вычислить смещение нужного вектора прерывания умножив номер вектора на 4 (длину far адреса в DOS). Например, вектор для 5-го прерывания (Print Screen) имеет смещение 20. Переведя 20 в шестнадцетиричное число, получим 14h, т.е. шестнадцетиричное смещение

  • Используя отладчик DEBUG с помощью команд:

DEBUG

-D 0000:0014 L 4

Получим содержимое четырех байтов в шестнадцетиричном виде:

54FF:00F0

Следует учитывать обратный порядок следования байтов:

54FF : 00F0

смещение : сегмент

младшая:старшая младшая:старшая части

В результате получим адрес – F000 : FF54

Для получения адреса обработчика можно также использовать 35 функцию ДОСа.

Код обработчика прерывания заканчивается командой iret (interrupt return). В коде эмуляции ДОСа iret надо найти по переходам и включить в листинг кода прерывания.

О функциях восьмого прерывания можно дополнительно прочитать http://www.frolov-lib.ru/books/bsp.old/v33/ch5.htm

Способы реализации доступа к управляющим регистрам и буферам

image

В конструкции современных персональных компьютеров используется выделенная высокоскоростная шина памяти. Эта шина предназначена для увеличения скорости обмена данными между процессором и памятью. Устройства ввода-вывода не могут «увидеть» адреса памяти, выставляемые процессором на эту шину, следовательно, они не могут реагировать на такие адреса.

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

Такое решение работоспособно, но требует дополнительного увеличения сложности аппаратуры.

image

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

Третий способ решения проблемы. Фильтрация адресов микросхемой моста PCI. Эта микросхема содержит регистры диапазона, заполняемые во время загрузки компьютера. Например, диапазон адресов от 640К до 1М может быть помечен как не относящийся к памяти. Все адреса, попадающие в подобный диапазон, передаются не памяти, а на шину PCI. Недостаток этой схемы состоит в необходимости принятия во время загрузки решения о том, какие адреса не являются адресами памяти.

ЛР1 ЧАСТЬ 2

  1. Особенности обработчика прерывания от системного таймера.

Обработчик прерывания от системного таймера выполняется на очень высоком уровне приоритета. Хотя для ОС Windows правильнее говорить: на высоком уровне IRQL (рис.1).

image

Прервать работу такого обработчика могут только прерывания IPI и Power. Обработчики аппаратных прерываний такие, как прерывания от внешних устройств и системного таймера, IPI и Power, должны завершаться как можно быстрее, чтобы не влиять на отзывчивость системы. У каждого типа соответствующего обработчика прерывания имеются свои особенности, связанные с возлагаемыми на них функциями. Обработчик прерывания от системного таймера выполняет очень важные функции, связанные с работой системы.

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

В книгах Д. Соломона, М. Русиновича нет отдельного параграфа, посвященного системному таймеру. Информацию следует искать во всем тексте.

Например, в Windows

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

На клиентских версиях Windows потоки по умолчанию выполняются в течение двух интервалов таймера (clock intervals), а на серверных системах по умолчанию поток выполняется в течение 12 интервалов таймера (о том, как изменить эти значения, будет рассказано в разделе «Управление величиной кванта»). Причина более продолжительного значения по умолчанию на серверных системах — стремление к минимизации контекстных переключений.

Продолжительность интервала таймера варьируется в зависимости от аппаратной платформы. Частота прерываний таймера зависит от HAL, а не от ядра. Например, интервал таймера на большинстве однопроцессорных систем x86 (они больше не поддерживаются Windows и упоминаются здесь только для примера) составляет около 10 миллисекунд, на большинстве многопроцессорных систем x86 и x64 он составляет порядка 15 миллисекунд. Величина интервала таймера хранится в переменной ядра KeMaximumIncrement в сотнях наносекунд.

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

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

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

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

Использование модели планирования, которая зависит только от интервального таймера, может привести к следующим ситуациям.

  • Потоки А и Б стали готовы к выполнению в середине интервала. (Код планирования запускается не по каждому интервалу времени, поэтому такое часто случается.)

  • Поток А начал выполняться, но его выполнение на какое-то время было прервано. Время, затраченное на обработку прерывания, потоку не возмещается.

  • Обработка прерывания завершается, и поток А снова запускается на выполнение, но быстро достигает следующего интервала таймера. Планировщик может только предположить, что поток А выполнялся все это время, и теперь переключается на выполнение потока Б.

  • Поток Б начинает выполняться и имеет шанс на выполнение в течение полного интервала таймера (если не брать в расчет вытеснение или обработку прерывания). И т.п.

Диспетчер настройки баланса находится в ожидании двух объектов событий: события от таймера, настроенного на срабатывание один раз в секунду, и события от внутреннего диспетчера рабочих наборов, которым диспетчер памяти подает сигнал в различные моменты, когда обнаруживает, что рабочие наборы нуждаются в настройке. Например, если система часто сталкивается с ошибками страниц или список свободных страниц слишком мал, диспетчер памяти активирует диспетчер настройки баланса, чтобы тот вызвал диспетчер рабочих наборов и приступил к усечению этих наборов. ...

Когда диспетчер настройки баланса активируется по тайм-ауту своего односекундного таймера, он выполняет следующие действия:.....

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

Кванты времени

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

На клиентских версиях Windows потоки по умолчанию выполняются в течение двух интервалов таймера (clock intervals), а на серверных системах по умолчанию поток выполняется в течение 12 интервалов таймера (о том, как изменить эти значения, будет рассказано в разделе «Управление величиной кванта»). Причина более продолжительного значения по умолчанию на серверных системах — стремление к минимизации контекстных переключений. За счет более продолжительного кванта времени серверные приложения, пробуждаемые в результате клиентского запроса, имеют более высокий шанс на завершение обработки запроса и возвращение в состояние ожидания до окончания их кванта времени.

И т.д.

Как видно из приведенных текстов в системе все не так однозначно и это надо попытаться отразить в отчете.

В Unix

image

Обработка прерываний таймера

image

Очевидно, что обработчик прерывания от системного таймера не может выполнять функции, относящие к работе планировщика и т.п. (рис.2):

image

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

Отложенные вызовы

image

Пересчет динамических приоритетов

Динамические приоритеты могут быть только у пользовательских процессов. В ОС процесс является владельцем ресурсов, в том числе владельцем приоритета. В разных ОС пересчет приоритетов выполняется по-разному.

В ОС Windows, как и в других семействах ОС процессу назначается приоритет, который затем по отношению к потокам рассматривается как базовый. Далее приведены фрагменты текста из книга «Внутреннее устройство Windows» 7е издание.

Так как переключение выполнения между потоками требует участия планировщика ядра, эта операция может быть довольно затратной, особенно если два потока часто передают управление между собой. В Windows реализованы два механизма для сокращения этих затрат: волокна (fibers) и планирование пользовательского режима (UMS, User Mode Scheduling). ...

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

Ядро создает системный поток, называемый диспетчером набора балансировки (balance set manager); он активизируется один раз в секунду для инициирования различных событий, связанных с планированием и управлением памятью. ...

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

  • критичный по времени — Time-critical (15);
  • наивысший — Highest (2);
  • выше обычного — Above-normal (1);
  • обычный — Normal (0);
  • ниже обычного — Below-normal (–1);
  • самый низший — Lowest (–2);
  • уровень простоя — Idle (–15).

Уровень, критичный по времени, и уровень простоя (+15 и –15) называются уровнями насыщения и представляют конкретные применяемые уровни вместо смещений. Эти значения могут передаваться API-функции SetThreadPriority для изменения относительного приоритета потоков. Таким образом, в Windows API каждый поток имеет базовый приоритет, являющийся функцией класса приоритета процесса и его относительного приоритета процесса. ...

В то время как у процесса имеется только одно базовое значение приоритета, у каждого потока имеется два значения приоритета: текущее (динамическое) и базовое. Решения по планированию принимаются исходя из текущего приоритета. Как поясняется в следующем разделе, посвященном повышениям приоритета, система при определенных обстоятельствах на короткие периоды времени повышает приоритет потоков в динамическом диапазоне (от 1 до 15). Windows никогда не регулирует приоритет потоков в диапазоне реального времени (от 16 до 31), поэтому они всегда имеют один и тот же базовый и текущий приоритет. Исходный базовый приоритет потока наследуется от базового приоритета процесса. Процесс по умолчанию наследует свой базовый приоритет у того процесса, который его создал. ... Ранее уже было показано, как код исполняющей системы отвечает за управление ресурсами исполняющей системы при таком развитии событий путем повышения приоритета потоков-владельцев, чтобы у них был шанс на выполнение и освобождение ресурса. Но ресурсы исполняющей системы являются только одной из многих конструкций синхронизации, доступной разработчикам, и технология повышения приоритета к любым другим примитивам применяться не будет. Поэтому в Windows также включен общий механизм ослабления загруженности центрального процессора, который называется диспетчером настройки баланса и является частью потока (речь идет о системном потоке, который существует главным образом для выполнения функций управления памятью — эта тема более подробно рассматривается в главе 5). Один раз в секунду этот поток сканирует очередь готовых по токов в поиске тех из них, которые находятся в состоянии ожидания (т. е. не были запущены) около 4 секунд. Если такой поток будет найден, диспетчер настройки баланса повышает его приоритет до 15 единиц и устанавливает квантовую цель эквивалентной тактовой частоте процессора при подсчете 3 квантовых единиц. Как только квант истекает, приоритет потока тут же снижается до обычного базового приоритета. Если поток не был завершен и есть готовый к запуску поток с более высоким уровнем приоритета, поток с пониженным приоритетом возвращается в очередь готовых потоков, где он опять становится подходящим для еще одного повышения приоритета, если будет оставаться в очереди следующие 4 секунды.

Диспетчер настройки баланса на самом деле при своем запуске сканирует не все потоки, находящиеся в состоянии готовности. Для минимизации затрачиваемого на его работу времени центрального процессора он сканирует только 16 готовых потоков; если на данном уровне приоритета имеется больше потоков, он запоминает то место, на котором остановился, и начинает с него при следующем проходе очереди. Кроме того, он за один проход повысит приоритет только 10 потоков, если найдет 10 потоков, заслуживающих именно этого повышения (что свидетельствует о необычно высоко загруженной системе), он прекратит сканирование на этом месте и начнет его с этого же места при следующем проходе. В ОС UNIX модуль ядра, который называется планировщиком (scheduler) создает очередь готовых к выполнению процессов.

Далее приведены соответствующих фрагменты текста из книги «Unix изнутри» Ю. Вахалия.

Планирование процессов

image

image

Планирование в традиционных системах UNIX

image

image

Приоритеты процессов

image

image

image

Реализация планировщика

image

Разширенные возможности системы Solaris 2.x

image

Вытесняющее ядро

image