Последната актуализация на този раздел е от 2020 година.

 

5.4.2  Обозначаване на прекъсванията

 

 

      Нека обърнем внимание на факта, че източниците на сигнали за прекъсване могат да бъдат много, а входовете за тях са много малко. С други думи, процесорът стои твърде високо в йерархията и точната идентификация на източника непосредствено е невъзможна. Ето защо естествено се налага прекъсванията да бъдат именовани и така лесно да бъдат различавани техните източници. Това значително облекчава намирането и стартирането на съответната обслужваща програма. Най-икономичното именоване е номерирането, така че в съвременните компютърни системи възможните източници на заявки за прекъсване, или на кратко – прекъсванията, получават уникални номера. Използваните числа като номера на прекъсванията, са числата от естествения ред в интервала [0,255], които като двоични имат дължина 8[b]. Както тук, така и в други литературни източници, номерът на прекъсването може да се нарича още код за прекъсване.

      Именоването на прекъсванията в компютърните системи на различните производители може да бъде и е различно. За това разбира се има обективни причини – концептуални и структурни, алгоритмични, софтуерни и др. Когато става дума обаче за съвместимост на компютърните системи с произвежданото за тях универсално външно оборудване, а така също и за съвместимост на софтуера, разработен за тях, положението се променя. Подобни общи качества за различни платформи могат да се осигурят при еднакво интерпретиране на събитията в компютърните системи. Ето защо за такива условия съществуват общоприети конвенции за разпределение на номерата на прекъсванията. Така например, за платформи с общо предназначение с архитектура IA-32, разпределението на номерата е известно и широко описано в литературата. За такива системи фирма Intel е резервирала номерата от 00 до 31 за обозначаване на изключенията. Цялостното разпределение за такива системи е представено в следващата таблица 5.4.2.1.

Таблица 5.4.2.1. Разпределение на номерата за прекъсване

Смисъл на събитието

Тип

Възможен рестарт

Код на грешката

Източник на събитието

0

Грешка при деление

Грешка

Да

Няма

Команди за деление DIV, IDIV.

1

При тестване

Грешка / Капан

Да

Няма

Всяка команда

2

Немаскируема ЗП (NMI)

Прекъсване

От следващата команда

Няма

Сигнал ЗП по вход NMI

3

Среща на контролна точка

Капан

От следващата команда

Няма

Команда  INT 3

4

Препълване

Капан

От следващата команда

Няма

Команда  INT 0

5

Нарушение на границите на масив

Грешка

Да

Няма

Команда  BOUND

6

Недействителен  КОП

Грешка

Да

Няма

Команда  UD2, неверен КОП, неверен операнд, опит за изпълнение на специална команда в Real Mode, невярно използване на префикс LOCK

7

Недостъпно устройство

Грешка

Да

Няма

ESC, команда  WAIT

8

Двойна грешка

Повреда

Не

0

Ако при тежко изключение2 (№0,10,11,12,13) или при странична грешка възникне още едно тежко изключение

9

резервирано

 

 

 

 

10

Недействителен  TSS1

Грешка

Да

Има

Команда

JMP, CALL, IRET, INT

11

Отсъства сегмент

Грешка

Да

Има

При опит да се зареди сегментен регистър или при команда  LDTR

12

Грешка в стека

Грешка

Да

Има

При операции със стека или при зареждане на  reg. SS

13

Нарушение на общата защита

Грешка / Капан

Да

Има

Всяко обръщение към паметта или при проверка на защитата

14

Странична грешка

Грешка

Да

Има

Всяко обръщение към паметта

15

резервирано

 

 

 

 

16

Грешка при плаваща запетая

Грешка

Да

Няма

ESC, команда  WAIT

17

Контрол на изравняване

Грешка

Да

0

Всяко обръщение към паметта

18

Машинен контрол

Повреда

Стоп

Зависи

Зависи от микропроцесора

19

Грешка  SIMD

Грешка

Да

Няма

Команди  SSE  или  SSE2

20 Έ 31

резервирани

 

 

 

 

32 Έ 255

Прекъсвания, определяни от потребителя

Прекъсване

Да

 

Команда  INT n  или външен сигнал

 

Забележка:

·         TSS1  (Task State Segment)  –  Сегмент за състоянието на задачата.

·         Тежко изключение2 – изключенията с номера 1,2,3,4,5,6,7,9,14,16 се наричат “леки”, защото не генерират двойна грешка. Само грешката при деление (0) и сегментните изключения (10,11,12 и 13) могат да предизвикат двойна грешка и затова се наричат “тежки”.

      Най-отляво е колонката на номера на прекъсването (от 0 до 255). Номерът на прекъсването n често се използва в машинните команди в качеството му на косвен адрес (вижте например, най-дясната колонка), той е удобно да бъде записван в 16-чна бойна система. В този смисъл записът  INT 0Dh  е еквивалентен на INT 13.

      В третата колонка е даден типът на прекъсването според класификацията от фигура 5.4.1.5. В четвъртата колонка става дума за това, как ще продължи изчислителният процес след обслужване на прекъсването. Възможностите са основно две – с продължение от следващата по ред команда или с повторно изпълнение на текущата (рестарт) – метод, който се практикува от Intel (вижте пункт 6.4.4). В петата колонка е посочен кодът на грешката при съответното прекъсване. Тук става дума за код, с който се идентифицира грешката и който може да се използва за определяна на причината, довела до изключението. Кодът на грешката се записва в стека със следния формат:

 

Фиг. 5.4.2.1.  Формат за съхранение кода на грешката

 

      Най-младшият бит (Е) определя прекъсването по външни причини (Е=1) или по вътрешни причини (Е=0). Бит №1 (I) означава дали индексът се отнася за таблицата на векторите за прекъсване (I=1). Индексът представлява число и се намира в разрядите от №3 до №15. Ако I=0 индексът се отнася за други таблици, които пък се определят от следващия бит №2 – бит Т, както следва: ако Т=0, това е индекс за GDT (глобалната дескрипторна таблица), а ако Т=1 е индекс за LDT (локалната дескрипторна таблица). Индексът има дължина 14 бита и служи за модифициране на старшите 14 бита в указателя на съответната таблица. По този начин едно прекъсване може да бъде обслужено от няколко различни програми, в зависимост от кода на грешката. Дали има смисъл това и кога е възможно едно прекъсване да се обработва от няколко програми – това са въпроси, които не са в кръга на нашите интереси тук.

      Във връзка с номерирането на прекъсванията съществува още една класификация:

1.       Прекъсвания на BIOS. Това са прекъсванията от №00 до №31 (00h, 1Fh) ;

2.       Прекъсвания на DOS. Това са прекъсвания с номер 32 (20h) и по-големи – до 255 (FFh).

Използване на номерата на прекъсванията

      Прекъсванията, или по-точно заявките за прекъсване, се явяват като сигнали, под формата на правоъгълни импулси. Тъй като те са много, идентификацията им се постига чрез техния номер. Този номер следва да бъде специфичен и уникален за източника, подал заявката. Тази уникалност трябва да бъде пренесена върху съответната програма от съвкупността обслужващи програми, което означава, че номерът на прекъсването е функционално свързан с началния адрес на съответната обслужваща програма – Апр=F(V). Тази функционалност се реализира в микропрограмната процедура за осъществяване на прекъсването МППОП (вижте фигура 5.4.1.2).

      Функционалността е следната: след приемане на заявката за прекъсване, следва нейното идентифициране, което се постига по различни начини, но в крайна сметка завършва, когато процесорът получи номера V на прекъсването. Този номер, за разлика от случая, представен на фигура 5.4.1.3, не може да се използва непосредствено в качеството му на адрес, най-малкото защото номерата са последователни, а обслужващите програми заемат много повече от една клетка. Номерът V на прекъсването следва да се превърне в адрес, но и това не може да бъде ефективния адрес за стартиране на обслужващата програма. Този адрес е табличен и ще бъде косвен адрес, адрес, който ще съдържа ефективния адрес. Така окончателно функционалното преобразуване на номера на прекъсването в адрес за преход можем да изразим по следния начин:

      В горната формула функцията F(V) изразява преобразуването на номера на прекъсването V в табличен адрес ТА, ТА=F(V). Този табличен адрес е косвен и неговото съдържание (ТА) следва да се извлече и използва като адрес за преход към съответната обслужваща програма. След казаното горната формула можем да запишем и така:

      Схемата на преход от сигнал към обслужваща програма е илюстрирана графично на долната фигура:

 

Фиг. 5.4.2.2.  Схема на прехода

 

      В процесора постъпва ЗП и нейният номер V. Номерът се преобразува апаратно в табличен адрес ТА, с който се прави обръщение към оперативната памет ОП. От там се извлича адресът за преход Апр, който се зарежда в програмния брояч.

      Всички 256 прекъсвания имат по един 4 байтов адрес, записан в таблицата с адресите за преход. Всеки един от тези адреси сочи началната команда на съответната обслужваща програма. По тази причина тези адреси се наричат вектори на прекъсване. Така таблицата с векторите има обем от 1024 байта, т.е. 1[KB]. От тук окончателно можем да формулираме функционалността F както следва:

F(V) = k.V  ,                  (5.4.2.3)

където с k е означен коефициентът на разслоено адресиране (вижте определението), който в дадения пример има стойността  k=4.

      При работа в реален режим (в DOS режим) в архитектурите IA-32 таблицата с векторите на прекъсване се намира в началото на адресното пространство (начален адрес на таблицата е адресът 00000000h) и тогава е в сила прякото съответствие: TA=F(V). Например, ако V=12, то адресът за преход към програмата, обслужваща това прекъсване, се намира в адрес ТА=48. Той заема 4 последователни клетки: 48,49,50 и 51.

      При работа в защитен режим, т.е. в режим на виртуална памет, таблицата с адресите на векторите за прекъсване (IDT – Interrupt Descriptor Table) може да бъде заредена от операционната система в произволно място в паметта. Тогава табличните адреси се изчисляват като относителни спрямо базовия адрес на таблицата, който е зареден от ОС в специален системен регистър IDTR:

TA = (IDTR) + k.V .             (5.4.2.4)

      Представените формули са принципни. В реалните процесори те се конкретизират.

Промени в таблицата на векторите за прекъсване

      Възможно е в една потребителска програма да се наложи обработката на заявка за дадено прекъсване да се извърши по нов алгоритъм. Причините за това могат да бъдат различни, например, включване в компютърната система на уникално новоразработено устройство. За стартиране на друга обработваща програма, различна от съдържащата се в операционната система, намираща се по друг начален адрес, се налага временна актуализация на съдържанието на таблицата на векторите за прекъсване. Много важно е при това да не се забрави, че преди връщане от обработката, следва да се възстанови старото съдържание на таблицата. Ако това не се направи има опасност от разрушаване, т.е. от неработоспособност на цялата система. Ето защо действията, които следва да изпълни една нерезидентна програма, желаеща сама да обработва дадено прекъсване, трябва да включват още следните действия:

1.       Да прочете съдържанието на онзи ред в таблицата на векторите, който съответства на номера използваното прекъсване ;

2.       Да запомни прочетеното от таблицата в своята даннова област ;

3.       Да запише в същия ред на таблицата назначеният от операционната система стартов адрес на нейната обработваща програма ;

4.       Преди да завърши изпълнението си, потребителското приложение следва да прочете от своята даннова област запомненият там стар вектор и да го запише в таблицата на векторите на същото му място.

      Важно е още да се знае, че действията по време на подмяната на векторите, трябва да бъдат непрекъсваеми от прекъсвания със същия номер (но при стария адрес). Това означава, че програмистът следва да управлява правилно цялата система за прекъсване – маски, нива, приоритет, режими и пр. За облекчаване работата на програмиста DOS предлага готови функции, предназначени за промяна на векторите за прекъсване. Такива библиотеки с готови функции предлагат някои програмни езици. Нашият интерес тук обаче е насочен в друго направление и няма да изясняваме тези софтуерни средства.

Технология Plug-and-Play (PnP)

      Тази технология е разработена с цел да улесни потребителя при добавяне на нов хардуер към компютърната конфигурация. Предлага се хардуерът да предоставя на програмното осигуряване възможности за гъвкаво конфигуриране. Така от своя страна софтуерът може да променя голяма част от настройките на хардуера, който става напълно “видим”. Най-съществената част това са номерата на прекъсване и входно-изходните адреси. В условията, когато тази технология е липсвала, конфигурирането на нов хардуер изисквало от потребителя отлично познаване на ресурсите на конкретната система. Ръчните настройки върху хардуера обикновено се реализират чрез набор от джъмпери (твърди превключватели). Всяка грешка при установяване на номер за прекъсване или на адрес води до неработоспособност. Ако хардуерните настройки минат (се възприемат) успешно, следващата стъпка за потребителя е да инсталира необходимите драйвери. Тук обаче също има уловка, тъй като драйверите не знаят какви настройки е избрал потребителя, а те трябва изрично да бъдат указани.

      Казаното изяснява мотивите на производителите да улеснят максимално потребителите. През годините са се появявали и изчезвали няколко решения на проблема. Първото масово реализиране на тази технология идва от фирмата Apple в началото на 80-те години на миналия век. Всеки нов хардуер в платформите на този производител се разпознава и конфигурира автоматично от операционната система. Това ниво на интеграция изисква наличие в системите на:

·      Стандартни протоколи за конфигуриране на хардуера ;

·      Пълна поддръжка на тези протоколи от страна на операционната система ;

·      Пълна поддръжка от страна на всяка дънна платка, в лицето на всеки BIOS.

      Успехът на Apple се дължал на това, че те са били производители както на хардуера, така и на операционната система.

      Почти 10 години по-късно Microsoft предлагат първото си решение по този проблем, масово приложено за първи път в операционната система Windows’95. Поддръжката на тази технология е наречена Plug-and-Play (Пъхни и Работи!). За съжаление невъзможността на огромния брой производители на хардуер за РС-платформите да предоставят 100% съвместими продукти в този смисъл, донесоха доста лоша слава на тази технология. Проблемите се съдържаха в лошо написаните драйвери или в непълната поддръжка на възможностите от страна на хардуера. Освен това, имплементацията на Microsoft не поддържа възможност за включване на хардуер при включена система, в резултат на което се появяват други технологии като например Hot-Plug.

      Интересен е фактът, че още през 1989 година асоциацията PCMCIA предлага пълно и работещо решение на проблемите, което обаче бива въплътено предимно в преносимите компютри.

Plug-and-Play върху шина PCI

      Всяко PCI-устройство има така нареченото конфигурационно пространство. Това пространство е с обем от 256 байта. Зад всеки адрес от това пространство стоят още две конфигурационни полета – за устройство и за функция, така че адресът се интерпретира според следната структура:

Адрес на шина [8 бита] :: Устройство [5 бита] :: Функция [3 бита]

      Това ни дава 256 шини, на всяка от тях могат да се мултиплексират до 32 устройства, всяко от които поддържа максимум 8 функции, който могат да бъдат адресирани и конфигурирани. Всяко PCI-устройство трябва да отговаря поне на функция номер 0. Първите 64 байта от конфигурационното пространство са стандартизирани, останалите са на разположение на производителите.

      При начално установяване на компютърната система се извършва “опипване“ (полинг) на PCI-шините като се опитва да се прочете VID/DID номера за всички възможни комбинации от шини::устройства::функции. VID (Vendor ID) е 16 битово число, уникален идентификатор на производителя. Този номер се издава от PCI SIG организацията. DID (Device ID) е също 16 битов уникален номер, указващ вида на устройството, който се издава от производителя. VID/DID стойностите се съдържат в стандартизирани регистри на устройството. Ако няма устройство което да отговори на запитването, контролерът на шината връща комбинацията 0xFFFFFFFF, която е приета като явен индикатор, че такова устройство не съществува. При на намиране на устройство, то бива конфигурирано, така че да няма конфликти с други такива. Конфигурацията се записва във временна памет на устройството и бива загубвана при рестарт.

Plug-and-Play върху шина Zorro

      Zorro е шина разработена от Amiga и използвана в техните компютри. Технологията Plug-and-Play се появява под наименованието Autoconfig. Интересна особеност е гъвкавостта и приложимостта на AmigaOS, която може да разпознае при работеща система допълнително количество оперативна памет и да я направи използваема на момента.

      При тази шина всяко устройство отговаря на определен фиксиран адрес в паметта, ако сигнал #CFGIN е активен. Началният адрес за устройствата преди Zorro-3 е бил E80000, а след версия 3 той е станал FF000000. Когато бъде открито устройство, се чете идентификатора на производителя, идентификатора на продукта и какво количество адресно пространство изисква устройството. След което бива конфигурирано и издава сигнал #CFGOUT. Сигналите #CFGIN и #CFGOUT са свързани каскадно между устройствата, така че когато едно бъде конфигурирано, устройството след него влиза във фаза на конфигурация и така докато се конфигурират всички устройства.

 

 

 

Следващият раздел е:

 

5.4.3.  Проблемът избор на заявка за прекъсване