Лекції "Системне програмування"

2. Лекція 3 Базові поняття ОС Windows

Базові поняття ОС Windows

 Переривання, виключення, системні виклики

У будь-якій операційній системі існує набір базових концепцій і базових механізмів, які стали невід'ємною частиною теорії і практики ОС.

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

Системні виклики (system calls) - механізм, що дозволяє призначеним для користувача програмам звертатися до послуг ядра ОС, тобто це інтерфейс між операційною системою і призначеної для користувача програмою. Концептуально системний виклик схожий на звичайний виклик підпрограми. Основна відмінність полягає в тому, що при системному виклику виконання програми здійснюється в привілейованому режимі або режимі ядра. Тому системні виклики іноді ще називають програмними перериваннями, на відміну від апаратних переривань, які частіше називають просто перериваннями. У більшості операційних систем системний виклик є результатом виконання команди програмного переривання (INT). Таким чином, системний виклик - це синхронна подія.

Переривання (hardware interrupt) - це подія, яка генерується зовнішнім (по відношенню до процесора) пристроєм. За допомогою апаратних переривань апаратура або інформує центральний процесор про те, що відбулася подія, що вимагає негайної реакції (наприклад, користувач натиснув клавішу), або повідомляє про завершення операції введення виведення (наприклад, закінчено читання даних з диска в основну пам'ять). Кожен тип апаратних переривань має власний номер, що однозначно визначає джерело переривання. Апаратне переривання - це асинхронна подія, тобто воно виникає незалежно від того, який код виконується процесором в даний момент. Обробка апаратного переривання не повинна враховувати, який процес або потік є поточним.

Виняткова ситуація (exception) - подія, що виникає в результаті спроби виконання програмою команди, яка з якихось причин не може бути виконана до кінця. Прикладами таких команд можуть бути спроби доступу до ресурсу за відсутності достатніх привілеїв або звернення до відсутньої сторінці пам'яті. Виняткові ситуації, як і системні виклики, є синхронними подіями, що виникають в контексті поточної задачі. Виняткові ситуації можна розділити на виправні і невиправні. До виправних відносяться такі виняткові ситуації, як відсутність потрібної інформації в оперативній пам'яті. Після усунення причини виправної виняткової ситуації програма може виконуватися далі. Виникнення в процесі роботи операційної системи виправних виняткових ситуацій вважається нормальним явищем. Невиправні виняткові ситуації найчастіше виникають в результаті помилок в програмах (наприклад, розподіл на нуль). Зазвичай в таких випадках операційна система реагує завершенням програми, що викликала виняткову ситуацію.

Застосовуючи структурну обробку виключень, можна спробувати "виправити" непоправну виняткову ситуацію, повернувши управління програмою, яка згенерувала цю ситуацію.

Приклад програми реалізує структурну обробку виключень

#include <stdio.h>

void main(){ 

int i = 1, j = 0, k = 0;

__try {

   k = i / j;

   puts("in try");

   printf("k=%d\n",k);

}

__except (1) {

   puts("in except");

   printf("k=%d\n",k);

}

}

Реалізація переривань, системних викликів і винятків
 в ОС Windows

Розглянемо реалізацію основних механізмів операційної системи в ОС Windows. Слід зазначити, що термінологія корпорації Microsoft дещо відрізняється від загальноприйнятої. Наприклад,

системні виклики називаються системними сервісами,

а під програмним перериванням розуміється виконання специфічних функцій ядра, що вимагають переривання роботи з поточною діяльністю.

Пастки (trap)

Загальним для реалізації розглянутих основних механізмів є необхідність збереження стану поточного потоку з його подальшим відновленням.

Для цього в ОС Windows використовується механізм пасток (trap). У разі виникнення вимоги обробки події (переривання, виключення або виклику системного сервісу) процесор переходить в привілейований режим і передає управління оброблювачу пасток, що входить до складу ядра. Оброблювач пасток створює в стеку ядра фрейм пастки, що містить частину контексту потоку для подальшого відновлення його стану, і в свою чергу передає управління певної частини ОС, що відповідає за первинну обробку події, що сталася .

У типовому випадку зберігаються і згодом відновлюються:

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

Ця інформація специфікована в структурі CONTEXT (файл winnt.h), і може бути отримана користувачем за допомогою функції GetThreadContext.

Адреса частини ядра ОС, відповідальної за обробку даного конкретного події визначається з вектору переривань, який номеру події ставить у відповідність адресу процедури його первинної обробки

Для асинхронних подій їх номер визначається контролером переривань, а для синхронних - ядром.

Процедура перегляду вектору переривань, який в термінології корпорації Microsoft називається таблицею диспетчеризації переривань (interrupt dispatch table, IDT), за допомогою відладчика kd.

Наприклад, для x86 процесора переривання від клавіатури відповідає номер 0x52, системним сервісів - 0x2e, а виняткової ситуації, пов'язаної з сторінкової помилкою, - 0xE (див. Мал. 3.1).

Після проходження первинної обробки для кожної події передбачена процедура його подальшої обробки іншими частинами ОС. Наприклад, обробка системного сервісу (системного виклику) передбачає передачу управління за адресою 0x2e, де розташовується диспетчер системних сервісів, якому через регістри EAX і EBX передаються номер запитаного сервісу і список параметрів, переданих цьому системному сервісу.

Те ж саме відбувається в разі виникнення виключень і переривань.

Прості виключення можуть бути оброблені диспетчером пасток, а більш складні обробляються диспетчером винятків, який може в разі виникнення виключення повернути управління додатку який викликав цей виняток. Це робиться за допомогою згаданого вище апарату структурної обробки виключень.

Вторинна обробка переривання забезпечується драйверами відповідних пристроїв.

Як приклад розглянемо процедуру обробки створення файлу.

Виклик Win32 функції CreateFile() генерує передачу управління функції NtCreateFile виконавчої системи, асемблерний код якої містить наступні операції:

mov ЕАХ, Ox17 номер системного сервісу для NtCreateFile

mov ebx, esp

int Ox2E обробка системного сервісу

ret Ox2C повернення управління

 

Пріоритети. IRQL

У більшості операційних систем апаратні переривання мають пріоритети, які визначаються контролерами переривань.

Однак ОС Windows має свою апаратно-незалежну шкалу пріоритетів, які називаються рівні запитів переривань (interrupt request levels, IRQL), і охоплює не тільки переривання, а всі події, що вимагають системної обробки. У таблиці 3.1 наведені значення IRQL рівнів для x86 систем.

Таблиця 3.1. Рівні запитів переривань (IRQL) в x86 системах

Рівень

Значення

Номер

High

Найвищий рівень

31

Power fail

Відмова електроживлення

30

Inter-process interrupt

між процесорний сигнал

29

Clock

Системний годинник

28

Profile

Контроль продуктивності ядра

27

Device n

Переривання від пристрою

26

Переривання від пристроїв

 

Device 1

Переривання від пристрою

3

DPC / dispatch

Відкладені операції і планування

2

APC

Асинхронні виклики процедур

1

Passive

Нормальне виконання потоків

0

 

Оброблювані події обслуговуються в порядку їх пріоритету, події з більш високим пріоритетом витісняють обробку подій з меншим пріоритетом. При виникненні події з високим пріоритетом IRQL процесора підвищується до рівня даної події. Після його обробки можуть проявити себе замасковані менш пріоритетні події, які, в свою чергу, можуть бути оброблені за звичайною схемою. Поточний рівень пріоритету зберігається в даних, що описують стан процесора, і може бути визначений системним відладчиком або за допомогою виклику функції KeGetCurrentIrql.

Значення IRQL для апаратних переривань розставляються диспетчером Plug and Play за допомогою рівня абстрагування від устаткування HAL, а для інших подій - ядром. Таким чином, рівень IRQL визначається джерелом події, що має інший зміст, ніж пріоритети в стратегії планування потоків. Розбиття на IRQL рівні є основним механізмом упорядкування за пріоритетами дій операційної системи.

Можна сказати, що в ОС Windows діє дворівнева схема планування. Пріоритети вищого рівня (в даному випадку IRQLs) визначаються апаратними або програмними перериваннями, а пріоритети нижчого рівня (в своєму діапазоні від 0 до 31) встановлюються для призначених для користувача потоків, які виконуються на нульовому рівні IRQL, і контролюються планувальником.

На нульовому (PASSIVE LEVEL) рівні IRQL працюють призначені для користувача процеси і частина коду операційної системи. Програма, що працює на цьому рівні, може бути витіснена майже будь-якою подією, що трапилася в системі.

Більшість процедур режиму ядра намагається утримувати IRQL процесора якомога нижчим.

IRQL рівні 1 (APC LEVEL) і 2 (DISPATCH LEVEL) призначені для так званих програмних (в термінології Microsoft) переривань відповідно:

 асинхронний виклик процедури - APC (asynchronous procedure call)

і до дзвінка процедури - DPC (deferred procedure call).

Якщо ядро приймає рішення виконати деяку системну процедуру, але немає необхідності робити це негайно, воно ставить її в чергу DPC і генерує DPC переривання.

Коли IRQL процесора стане досить низьким, ця процедура виконується. Характерний приклад - відкладена операція планування. З цього випливає, що код, що виконується на IRQL рівні, вище або дорівнює 2, не схильний до операції планування.

Асинхронний виклик процедур - механізм, аналогічний механізму DPC, але більш загального призначення, зокрема, доступний для процесів користувача.

IRQL рівні 3-26 відносяться до звичайних переривань від пристроїв.