| Каталог | Индекс раздела |
| Назад | Оглавление | Вперед |
| 0 | - игнорировать ошибку; |
| 1 | - повторить операцию; |
| 2 | - завершить программу; |
| 3 | - снять системный вызов, в котором произошла ошибка. |
В программном примере 14.1 устанавливается собственный
обработчик ошибки, который запоминает информацию об ошибке и
заканчивается с кодом 3 - снять системный вызов. Информация
об ошибке затем распечатывается.
Ошибочные ситуации, которые возникают при работе примера
14.1, - чтение информации с неготового диска и вывод на неготовый принтер. Читатель может самостоятельно расширить
пример другими сбойными ситуациями.
/*==== ПРИМЕР 14.1 ====*/
/*==== Обработка критической ошибки ====*/
#include <dos.h>
#include <stdio.h>
#define byte unsigned char
#define word unsigned int
void interrupt new_24();
void interrupt (* old_24)(); /* адрес старого обработчика критической ошибки */
/* информация об ошибке, запомненная в обработчике */
byte save_ah, save_al, class, actions;
word save_di, save_bp, save_si, ext_code, locate;
/* сообщения */
char *msg1[]= {"ИГНОРИРОВАТЬ","ПОВТОРИТЬ","СНЯТЬ"};
char *msg2[]=
{"системная обл.","FAT","каталог","обл.данных"};
char *msg3[]={"защита от записи","неизвестное устройство",
"диск не готов","неизвестная команда","ошибка CRC",
"неправильная структура запроса","ошибка поиска",
"неизвестный тип диска","сектор не найден",
"конец бумаги","ошибка записи","ошибка чтения",
"общий сбой","наруш.режима разделения",
"наруш.блокировки","ошибка смены диска",
"FCB недоступен","переполн.буфера разделения" };
union REGS rr;
struct SREGS sr;
int dos;
FILE *f;
main() {
/* получить версию DOS */
rr.h.ah=0x30; intdos(&rr,&rr);
if ((dos=rr.h.al)==3) dos=0;
/* перехват вектора */
old_24=getvect(0x24); setvect(0x24,new_24);
/* эксперимент 1 */
save_ah=save_al=save_di=save_bp=save_si=0;
/* получить адрес DPB (при неготовом диске) */
rr.h.ah=0x32;
rr.h.dl=2;
intdosx(&rr,&rr,&sr);
error_scan();
/* эксперимент 2 */
save_ah=save_al=save_di=save_bp=save_si=0;
/* печатать (при неготовом принтере) */
fprintf(stdprn,"aaa");
error_scan();
/* восстановление вектора (необязательно) */
setvect(0x24,old_24);
}
/*-------------------------------------*/
/*== Распечатка информации об ошибке ==*/
error_scan() {
int i; byte k; char *s;
if (!(save_ah|save_al|save_di|save_bp|save_si))
printf("Ошибки нет\n");
else {
printf("\nОшибка при ");
if (save_ah&1) printf("записи, ");
else printf("чтении, ");
if (save_ah&0x80){
printf("устройство ");
s=(char far *)MK_FP(save_bp,save_si)+10;
for (i=0; i<8; i++,s++) printf("%c",*s);
printf("\n");
}
else {
printf("диск %c\n",save_al+'A');
printf("Место ошибки - %s\n",msg2[(save_ah>>1)&3]);
}
for (i=0,k=0x20; k>0x04; k>>=1,i++)
if (save_ah&k) printf("Можно %s\n",msg1[i]);
else printf("Нельзя %s\n",msg1[i]);
printf("Тип ошибки - %s\n",msg3[save_di]);
printf("РАСШИРЕННАЯ ИНФОРМАЦИЯ:\n");
printf(" Код ошибки - %04Xh\n",ext_code);
printf(" Класс ошибки - %02Xh\n",class);
printf(" Действия - %02Xh\n",actions);
printf(" Место - %02Xh\n",locate);
}
printf("Нажмите любую клавишу...\n"); getch();
}
/*-------------------------------------*/
/*== Обработчик критических ситуаций ==*/
void interrupt new_24
(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flgs)
word bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flgs; {
/* сохранение основной информации об ошибке */
save_ah=ax>>8; save_al=ax&0xff; save_di=di;
save_bp=bp; save_si=si;
/* получение расширенной информации об ошибке */
rr.h.ah=0x59; /* функция 59 */
rr.x.bx=dos;
intdos(&rr,&rr);
ext_code=rr.x.ax;
class=rr.h.bh;
actions=rr.h.bl;
locate=rr.h.ch;
/* действия - отменить запрос */
ax=3;
}
14.2. Расширенная информация об ошибке.
Начиная с DOS 2.0, те функции DOS, при выполнении которых могут возникать ошибки, индицируют наличие ошибки установкой флага CY, при этом регистр AX содержит код ошибки. Следующие коды ошибок могут возвращаться в регистре AX:
Расширенные коды ошибок:
| 19 - 36 | -соответствуют кодам 0 - 17, передаваемым обработчику критической ошибки в регистре DI; |
| 36 - 49 | -зарезервировано; |
| 50 - 60 | -ошибки, связанные с работой в сети; |
| 61 - 63 | -ошибки спуллинга печати; |
| 55 - 72 | -ошибки, связанные с работой в сети; |
| 73 - 79 | -зарезервировано; |
| 80 | -файл уже существует; |
| 81 | -зарезервировано; |
| 82 | -невозможно создать элемент каталога; |
| 83 | -сбой при обработке прерывания по критической ошибке; |
| 84 | -слишком много перенаправлений; |
| 85 | -повторяющееся перенаправление; |
| 86 | -неправильный пароль; |
| 87 | -неправильный параметр; |
| 88 | -ошибка в данных сети. |
Классы ошибок:
| 1 | -нехватка ресурса (памяти, описателей файлов и т.п.); |
| 2 | -временная ситуация; |
| 3 | -превышение пользователем своих полномочий; |
| 4 | -внутренняя ошибка DOS; |
| 5 | -ошибка оборудования; |
| 6 | -системная ошибка DOS; |
| 7 | -ошибка применения (некорректный запрос, неверные параметры и т.п.); |
| 8 | -запрошенный файл или другой объект найден; |
| 9 | -неверный формат файла, диска и т.п.; |
| 10 | -файл или другой объект захвачен другим пользователем; |
| 11 | -ошибка носителя; |
| 12 | -файл или другой объект уже существует; |
| 13 | -неивестный класс. |
Предполагаемые действия:
| 1 | -повторить операцию несколько раз; |
| 2 | -повторить операцию после задержки; |
| 3 | -повторить ввод данных для DOS пользователем; |
| 4 | -снять задачу, выполнив операции завершения (закрытие файлов, обновление индексов, освобождение памяти и т.п.); |
| 5 | -снять задачу, не выполняя операции завершения; |
| 6 | -игнорировать ошибку; |
| 7 | -повторить операцию после выполнения пользователем каких-то действий. |
Локализация ошибки:
| 1 | -место ошибки не определено; |
| 2 | -ошибка на блочном устройстве; |
| 3 | -зарезервировано; |
| 4 | -ошибка на символьном устройстве; |
| 5 | -ошибка в памяти. |
Обработчик критической ошибки в примере 14.1 обращается к функции 0x59 и запоминает также расширенную информацию об ошибке. Чтобы не перегружать пример строковыми константами на печать выводятся только коды ошибки, класса и т.д., а не смысловые сообщения.
| Каталог | Индекс раздела |
| Назад | Оглавление | Вперед |