Изучение основных принципов организации и обслуживания аппаратных прерываний в ОС DOS и QNX, страница 2

Tue Jan  1 08:48:31 2002

3.2. Транзитная программа вывода текущего времени с выходом по клавише.

Текст программы для QNX:

#include <stdio.h>

//для работы с прерываниями

#include <sys/neutrino.h>

//для обработки ошибок

#include <errno.h>

//для работы с сигналами

#include <signal.h>

//для работы с портом клавиатуры

#include <hw/inout.h>

//обработчик прерывания от таймера

//возвращает указатель на событие

//аргументы: area и идентификатор

const struct sigevent* timer0_int (void *area, int id);

//обработчик прерывания от клавиатуры

const struct sigevent* klav_int (void *area, int id);

struct sigevent time_event;

struct sigevent klav_event;

//может измениться в любой момент, не кэшировать

volatile int counter=0;

int main (void) {

      int inter_id, inter_id2;

      time_t cur_time;

      //запрос на использование привиллегированного ввода/вывода

      //(для возможности использования прерываний)

      ThreadCtl(_NTO_TCTL_IO,0);

      //макрос для определения типа  "прерывание" структуры sigevent

      SIGEV_INTR_INIT(&time_event);

      //макрос для определения типа  "сигнал" структуры sigevent

      SIGEV_SIGNAL_INIT(&klav_event,SIGKILL);

      //подключние обработчика прерывания

      inter_id=InterruptAttach(0, timer0_int, NULL,0,0);

      //проверка на наличие ошибок

      if (inter_id == -1) {

            printf("%s\n",strerror(errno));

            return 1;

      }

      inter_id2=InterruptAttach(1, klav_int, NULL,0,0);

      //проверка на наличие ошибок

      if (inter_id2 == -1) {

            printf("%s\n",strerror(errno));

            return 1;

      }

      while (1) {

            //ждем события "прерывание"

            InterruptWait(NULL,NULL);

            cur_time=time(NULL);

            printf("%s",ctime(&cur_time));

      }

}

const struct sigevent *timer0_int (void *area, int id) {

      counter++;

      //если прошло 1000 мс, обнуляем счетчик и генерируем событие

      if (counter == 1000) {

            counter = 0;

            return &time_event;

      }

      else return NULL;

}

const struct sigevent *klav_int (void *area, int id) {

      int code;

      code=in8(0x60);

      if (code == 1)    //код???!!!

            return &klav_event;

      return NULL;

}

Результаты испытаний:

# ./print_time_ex.out

Tue Jan  1 08:50:59 2002

Tue Jan  1 08:51:00 2002

Tue Jan  1 08:51:01 2002

Tue Jan  1 08:51:02 2002

Killed

#

Текст программы для DOS:

;запись символа из параметра #2 в видеобуфер со смещением заданным в параметре #1

print macro

      push  ax, ds, es  ;сохранение используемых ресурсов

      mov   ax, 0b800h  ; адрес сегмента текстовой видеопамяти

            mov  es, ax            ; равен 0B800h,

      mov   di, #1            ;смещение

      mov   ah, 0fh           ;цвет

      mov   al, #2            ;выводимый символ

      mov   es:[di], ax ;запись цвета и кода символа непосредственно в                                     ;видеобуфер

      pop   es, ds, ax  ;восстановление ресурсов

#em

;преобразование параметра #2 в ASCII код и вывод его в видеобуфер со смещением #1

print_sm macro

      push  ax, cx            ;сохранение используемых ресурсов