Управление обработкой прерываний (irq.h)

21 мая 2024

ID libkos_irq_api

API определен в заголовочном файле sysroot-*-kos/include/coresrv/io/irq.h из состава KasperskyOS SDK.

API позволяет управлять обработкой аппаратных прерываний. Аппаратное прерывание – это сигнал процессору от устройства о необходимости немедленно переключиться с исполнения текущей программы на обработку события, связанного с этим устройством. Например, нажатие клавиши на клавиатуре вызывает аппаратное прерывание, которое обеспечивает требуемую реакцию на это нажатие (к примеру, ввод символа).

Аппаратное прерывание возникает при обращении устройства к контроллеру прерываний. Это обращение может осуществляться через линию аппаратного прерывания между устройством и контроллером прерываний или через память MMIO. Во втором случае устройство выполняет запись в память MMIO, вызывая прерывание MSI (англ. Message Signaled Interrupt).

В настоящее время функции для управления обработкой прерываний MSI не реализованы.

Каждой линии аппаратного прерывания соответствует одно прерывание с уникальным номером.

Сведения о функциях API приведены в таблице ниже.

Использование API

Чтобы связать прерывание с его обработчиком, нужно выполнить следующие шаги:

  1. Регистрация прерывания вызовом функции KnRegisterIrq().

    Одно прерывание можно зарегистрировать несколько раз в одном или нескольких процессах.

    Дескриптор прерывания можно передать другому процессу через IPC.

  2. Привязка потока исполнения к прерыванию вызовом функции KnIoAttachIrq().

    Этот шаг выполняется потоком исполнения, в контексте которого будет выполняться обработка прерывания.

    Используя дескриптор, полученный при вызове функции KnRegisterIrq(), можно привязать к прерыванию только один поток исполнения. Чтобы привязать к прерыванию несколько потоков исполнения в одном или нескольких процессах, нужно использовать разные дескрипторы этого прерывания, полученные при отдельных вызовах функции KnRegisterIrq(). В этом случае функцию KnIoAttachIrq() нужно вызывать с одними и теми же флагами в параметре flags.

    Дескриптор, полученный при вызове функции KnIoAttachIrq(), нельзя передать другому процессу через IPC.

Чтобы запретить (маскировать) прерывание, нужно вызвать функцию KnIoDisableIrq(). Чтобы разрешить (демаскировать) прерывание, нужно вызвать функцию KnIoEnableIrq(). И хотя эти функции принимают дескриптор прерывания, через который к прерыванию привязан только один поток исполнения, их действие распространяется на все потоки исполнения, привязанные к этому прерыванию. Эти функции нужно вызывать вне потоков исполнения, привязанных к прерыванию. После регистрации прерывания и привязки к нему потока исполнения это прерывание не требуется демаскировать.

Чтобы инициировать отвязывание потока исполнения от прерывания, нужно вызвать функцию KnIoDetachIrq() вне потока исполнения, привязанного к прерыванию. Отвязывание выполняет поток исполнения, привязанный к прерыванию, вызовом функции KnThreadDetachIrq(), объявленной в заголовочном файле sysroot-*-kos/include/coresrv/thread/thread_api.h. из состава KasperskyOS SDK.

Обработка прерывания

После выполнения привязки к прерыванию поток исполнения вызывает функцию Call(), объявленную в заголовочном файле sysroot-*-kos/include/coresrv/syscalls.h из состава KasperskyOS SDK. В результате этого вызова поток исполнения блокируется. При возникновении прерывания или вызове функции KnIoDetachIrq() ядро KasperskyOS отправляет IPC-сообщение процессу, содержащему этот поток. Это IPC-сообщение содержит запрос на обработку прерывания или запрос на отвязывание потока исполнения от прерывания. Когда процесс получает IPC-сообщение, функция Call() в потоке исполнения, привязанном к прерыванию, возвращает управление и предоставляет потоку содержимое IPC-сообщения. Поток исполнения извлекает из IPC-сообщения запрос и обрабатывает прерывание либо выполняет отвязывание от прерывания. Если выполняется обработка прерывания, то по ее завершении сведения об успехе или неуспехе обработки добавляются в ответное IPC-сообщение, которое отправляется ядру следующим вызовом функции Call() в цикле.

При обработке прерывания нужно использовать функции IoGetIrqRequest() и IoSetIrqAnswer(), которые объявлены в заголовочном файле sysroot-*-kos/include/io/io_irq.h из состава KasperskyOS SDK. Эти функции позволяют извлекать из IPC-сообщений и добавлять в IPC-сообщения данные для информационного обмена между ядром и потоком исполнения, привязанным к прерыванию.

Типовой цикл обработки прерывания включает следующие шаги:

  1. Добавление в IPC-сообщение, которое будет отправлено ядру, сведений об успехе или неуспехе обработки прерывания вызовом функции IoSetIrqAnswer().
  2. Отправка IPC-сообщения ядру и получение IPC-сообщения от ядра.

    Чтобы выполнить этот шаг, нужно вызвать функции Call(). В параметре handle требуется указать дескриптор, полученный при вызове функции KnIoAttachIrq(). Через параметр msgOut необходимо задать IPC-сообщение, которое будет отправлено ядру, а через параметр msgIn необходимо задать IPC-сообщение, которое будет получено от ядра.

  3. Извлечение запроса из IPC-сообщения, полученного от ядра, вызовом функции IoGetIrqRequest().
  4. Обработка прерывания или отвязывание от прерывания в зависимости от запроса.

    Если запрос требует выполнить отвязывание от прерывания, то нужно выйти из цикла обработки прерывания и вызвать функцию KnThreadDetachIrq().

Дерегистрация прерывания

Чтобы дерегистрировать прерывание, нужно выполнить следующие шаги:

  1. Выполнить отвязывание потока исполнения от прерывания.

    Чтобы выполнить этот шаг, нужно вызвать функцию KnThreadDetachIrq().

  2. Закрыть дескриптор, полученный при вызове функции KnIoAttachIrq().

    Чтобы выполнить этот шаг, нужно вызвать функцию KnHandleClose(). (Функция KnHandleClose() объявлена в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h из состава KasperskyOS SDK.)

  3. Закрыть или отозвать каждый дескриптор прерывания во всех процессах, которые владеют этими дескрипторами.

    Чтобы выполнить этот шаг, нужно использовать функцию KnHandleClose() и/или KnHandleRevoke(), которые объявлены в заголовочном файле sysroot-*-kos/include/coresrv/handle/handle_api.h из состава KasperskyOS SDK.

Одно прерывание может быть зарегистрировано несколько раз, а выполнение этих шагов аннулирует только одну регистрацию. Оставшиеся регистрации продолжают действовать. Каждую регистрацию одного прерывания нужно аннулировать отдельно.

Сведения о функциях API

Функции irq.h

Функция

Сведения о функции

KnRegisterIrq()

Назначение

Регистрирует прерывание.

Параметры

  • [in] irq – номер прерывания.
  • [out] outRid – указатель на дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoAttachIrq()

Назначение

Привязывает вызывающий поток исполнения к прерыванию.

Параметры

  • [in] rid – дескриптор прерывания.
  • [in] flags – флаги, задающие параметры прерывания. Флаги определены в заголовочных файлах sysroot-*-kos/include/io/io_irq.h и sysroot-*-kos/include/hal/irqmode.h из состава KasperskyOS SDK.
  • [out] handle – указатель на клиентский IPC-дескриптор, который используется обработчиком прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Дополнительные сведения

В параметре flags можно указать следующие флаги:

  • IRQ_LEVEL_LOW – прерывание возникает при низком уровне сигнала.
  • IRQ_LEVEL_HIGH – прерывание возникает при высоком уровне сигнала.
  • IRQ_EDGE_RAISE – прерывание возникает при повышении уровня сигнала.
  • IRQ_EDGE_FALL – прерывание возникает при снижении уровня сигнала.
  • IRQ_PRIO_LOW – прерывание имеет низкий приоритет.
  • IRQ_PRIO_NORMAL – прерывание имеет средний приоритет.
  • IRQ_PRIO_HIGH – прерывание имеет высокий приоритет.
  • IRQ_PRIO_RT – прерывание имеет наивысший приоритет.

KnIoDetachIrq()

Назначение

Отправляет потоку исполнения запрос, в результате выполнения которого поток должен выполнить отвязывание от прерывания.

Параметры

  • [in] rid – дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoEnableIrq()

Назначение

Разрешает (демаскирует) прерывание.

Параметры

  • [in] rid – дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

KnIoDisableIrq()

Назначение

Запрещает (маскирует) прерывание.

Параметры

  • [in] rid – дескриптор прерывания.

Возвращаемые значения

В случае успеха возвращает rcOk, иначе возвращает код ошибки.

Вам помогла эта статья?
Что нам нужно улучшить?
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!