Скачиваний:
39
Добавлен:
01.05.2014
Размер:
13.21 Кб
Скачать

Untitled Программы •Железо • Драйверы • Хостинг •Энциклопедия рекламы5. Обработка критических ошибок Операционная система MS-DOS позволяет программам устанавливать собственный обработчик критических ошибок аппаратуры. Мы уже говорили о том, что вектор 0000:0090, соответствующий прерыванию INT 24h, содержит адрес обработчика критических ошибок. Этот обработчик получает управление от операционной системы, когда драйвер какого-либо устройства обнаруживает ошибку аппаратуры. Обратите внимание на то, что обработчик критических ошибок не вызывается при работе с диском через прерывания MS-DOS INT 25h/26h, и, тем более, при работе с диском на уровне прерывания INT 13h BIOSBIOS. При запуске программы MS-DOS копирует адрес обработчика в префикс сегмента программы PSP, а после завершения работы программы - восстанавливает его из PSP. Стандартный обработчик MS-DOS выводит на экран сообщение: Abort, Retry, Ignore, Fail? Если ваша программа должна сама обрабатывать ошибки аппаратуры, она может установить свой собственный обработчик критических ошибок. Когда обработчик получает управление, регистры процессора содержат информацию, необходимую для определения причины и места появления ошибки:

AHинформация об ошибке:

Биты:

0 - тип операции:

0 - чтение, 1 - запись

1...2 область диска, где произошла ошибка:

00 - системные файлы;

01 - область FAT

10 - область каталога;

11 - область данных

3 - 1 - возможен выход с кодом FAIL

4 - 1 - возможен выход с кодом RETRY

5 - 1 - возможен выход с кодом IGNORE

6 зарезервирован, равен 0

7 тип устройства: 0 - диск; 1 - символьное устройство ALномер диска (если бит 7 регистра AH равен 0) DIкод ошибки (биты 0...7, остальные биты не определены) BP:SIадрес заголовка драйвера устройства, на котором произошла ошибка Биты 3, 4, 5 определены только для DOS версии 3.0 и для более поздних версий. Обработчик критических ошибок не должен пользоваться функциями MS-DOS с кодами, большими чем 0Ch (из-за того, что функции MS-DOS не реентерабельны). Программа может вывести на экран сообщение об ошибке и запросить оператора о необходимых действиях. Ей разрешено также получить дополнительную уточняющую информацию об ошибке с помощью функции 59h прерывания INT 21h или узнать версию DOS с помощью функции 30h этого же прерывания. Дополнительная информация об устройстве, в котором произошла ошибка, может быть получена с использованием адреса заголовка драйвера устройства, который передается операционной системой при вызове обработчика в регистрах BP:SI. Для определения номера функции DOS, в которой произошла критическая ошибка, программа-обработчик может выполнить анализ стека. Когда обработчик получает управление, стек имеет следующую структуру: Адрес возврата в DOS для команды IRET IP CS FLAGS Содержимое регистров программы перед вызовом INT_21h AX, BX, CX, DX, SI, DI, BP, DS, ES Адрес возврата в программу, вызвавшую функцию DOS IP CS FLAGS Выполнив анализ регистра AH, можно определить номер функции DOS, при вызове которой произошла ошибка, а зная содержимое остальных регистров - и все параметры этой функции. После выполнения всех необходимых действий, программа обработки критических ошибок должна возвратить в регистре AL код действия, которое должна выполнить операционная система для обработки данной ошибки:

0игнорировать ошибку; 1повторить операцию; 2аварийно закончить задачу, используя адрес завершения, записанный в векторе прерывания INT 23h; 3вернуть программе управление с соответствующим кодом ошибки (этот код можно задавать только для DOS версии 3.0 и для более поздних версий). Если вы пользуетесь операционной системой MS-DOS версии 4.0, то при открытии файлов с помощью функции 6Ch программа может заблокировать вызов обработчика критических ошибок. Для составления программы обработки критических ошибок вы можете воспользоваться языком ассемблера или функциями стандартных библиотек трансляторов Microsoft QC 2.5 и C 6.0 _dos_getvect(), _dos_setvect(), _chain_intr(). Однако лучше всего использовать специально предназначенные для этого (и входящие в состав стандартных библиотек указанных трансляторов) функции _harderr(), _hardresume() и _hardretn(). Функция _harderr() предназначена для установки нового обработчика критических ошибок, она имеет следующий прототип: void _harderr(void (_far *handler)()); Параметр handler - указатель на новую функцию обработки критических ошибок. Функции _hardresume() и _hardretn() должны быть использованы в обработчике критичеких ошибок, установленном функцией _harderr(). Функция _hardresume() возвращает управление операционной системе, она имеет прототип: _hardresume(int result); Парметр result может иметь следующие значения (в соответствии с необходимыми действиями):

_HARDERR_ABORTаварийно завершить программу; _HARDERR_FAILвернуть код ошибки; _HARDERR_IGNOREигнорировать ошибку; _HARDERR_RETRYповторить операцию. Эти параметры описаны в файле dos.h. Функция _hardretn() возвращает управление непосредственно программе, передавая ей код ошибки, определяемый параметром функции error: void _hardretn(int error); При этом программа получает после возврата из вызванной ей функции DOS код ошибки error. Если ошибка произошла при выполнении функции с номером, большим чем 38h, дополнительно устанавливается в 1 флаг переноса. Если номер функции был меньше указанного значения, в регистр AL записывается величина FFh. Функция обработки критических ошибок handler имеет следующие параметры: void _far handler(unsigned deverror, unsigned errcode, unsigned _far *devhdr); Первый параметр - код ошибки устройства. Он равен содержимому регистра AX при вызове обработчика прерывания INT 24h. Аналогично, параметр errcode соответствует содержимому регистра DI - код ошибки. Третий параметр - devhdr - это указатель на заголовок драйвера устройства (передаваемый в регистрах BP:SI). Для демонстрации использования функций установки обработчика критических ошибок приведем программу, которая пытается создать каталог на диске А:. Эта программа сама обрабатывает критические ошибки, запрашивая у оператора информацию о необходимых действиях. // Эту программу можно запускать только из командной // строки. При запуске из интегрированной среды QC // или PWB возможен конфликт с используемым в этих // средах обработчиком критических ошибок. #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <direct.h> #include <string.h> #include <dos.h> #include <bios.h> void main(void); void _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr); void _bios_str(char *p); void main() { // Устанавливаем обработчик критических ошибок _harderr(hhandler); // Моделируем критическую ошибку. Выполняем попытку создать // каталог на диске А:. Если мы "забудем" вставить // в дисковод дискету, будет вызван обработчик // критической ошибки printf("\nВставьте (или не вставляйте) дискету в дисковод A:" "\nи нажмите любую клавишу..." "\n"); getch(); // Создаем каталог if(mkdir("a:\test_ctl")) { printf("\nОшибка при создании каталога" ); exit(-1); } else { printf("\nУспешное создание каталога"); // Удаляем только что созданный каталог rmdir("a:test_ctl"); exit(0); } } // Новый обработчик критических ошибок void _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr) { int ch; static char buf[200], tmpbuf[10]; // Выводим сообщение о критической ошибке sprintf(buf,"\n\r" "\n\rКод ошибки устройтсва: %04.4X" "\n\rКод ошибки DOS: %d" "\n\r\n\r" "\n\rВыполняемые действия:" "\n\r 0 - повторить" "\n\r 1 - отменить" "\n\r 2 - завершить" "\n\r----> ?", deverr, doserr); _bios_str(buf); // Вводим ответ с клавиатуры ch = _bios_keybrd(_KEYBRD_READ) & 0x00ff; _bios_str("\n\r"); switch(ch) { case '0': // Пытаемся повторить операцию default: _hardresume(_HARDERR_RETRY); case '2': // Завершаем работу программы _hardresume(_HARDERR_ABORT); case '1': // Возврат в DOS с кодом ошибки _hardretn(doserr); } } // Программа для вывода строки символов на экран // с помощью функции BIOS 0Eh void _bios_str(char *ptr) { union REGS inregs, outregs; char *start = ptr; inregs.h.ah = 0x0e; for(; *ptr; ptr++) { inregs.h.al = *ptr; int86(0x10, &inregs, &outregs); } }

Соседние файлы в папке 3 Том