Флаг прерывания ( IF ) — это бит флага в регистре FLAGS ЦП , который определяет, будет ли ЦП немедленно реагировать на маскируемые аппаратные прерывания . [1] Если флаг установлен в значение , маскируемые прерывания разрешены . Если сброшен (установлен в значение ), такие прерывания будут запрещены до тех пор, пока прерывания не будут разрешены. Флаг прерывания не влияет на обработку немаскируемых прерываний (NMI) или программных прерываний, генерируемых инструкцией INT .1
0
В системе с архитектурой x86 используются инструкции CLI ( Clear Interrupt ) и STI ( Set Interrupt ). POPF ( Pop Flags ) удаляет слово из стека в регистр FLAGS , что может привести к установке или сбросу флага прерывания в зависимости от бита в регистре FLAGS в верхней части стека. [1]
В системах, поддерживающих привилегированный режим, только привилегированные приложения (обычно ядро ОС ) могут изменять флаг прерывания . В системе x86 это применимо только к коду защищенного режима (код реального режима всегда может изменять флаг прерывания ). CLI и STI являются привилегированными инструкциями, которые вызывают общую ошибку защиты, если непривилегированное приложение пытается их выполнить. Инструкция POPF не изменит флаг прерывания , если приложение не является привилегированным.
Некоторые старые программы DOS , которые используют защищенный режим DOS-расширения и устанавливают свои собственные обработчики прерываний (обычно игры), используют инструкцию CLI в обработчиках для отключения прерываний и либо POPF (после соответствующего PUSHF), либо IRET (которая восстанавливает флаги из стека как часть своих эффектов) для их восстановления. Это работает, если программа была запущена в реальном режиме, но вызывает проблемы, когда такие программы запускаются в контейнере на основе DPMI в современных операционных системах (например, NTVDM под Windows NT или более поздней версии). Поскольку CLI является привилегированной инструкцией, она вызывает ошибку в операционной системе, когда программа пытается ее использовать. Затем ОС обычно прекращает доставку прерываний программе, пока программа не выполнит STI (что вызвало бы другую ошибку). Однако инструкция POPF не является привилегированной и просто молча не восстанавливает IF. В результате ОС прекращает доставку прерываний программе, которая затем зависает. Программы DOS, не использующие расширитель защищенного режима, не страдают от этой проблемы, поскольку они выполняются в режиме V86, где POPF вызывает ошибку.
Существует несколько удовлетворительных решений этой проблемы. Обычно невозможно изменить программу, поскольку исходный код обычно недоступен, а в потоке инструкций нет места для введения STI без масштабного редактирования на уровне сборки. Удаление CLI из программы или полное игнорирование CLI хостом V86 может привести к другим ошибкам, если обработчики прерываний гостя не предназначены для повторного входа (хотя при выполнении на современном процессоре они обычно выполняются достаточно быстро, чтобы избежать перекрытия прерываний).
В наборе инструкций x86 CLI обычно используется как механизм синхронизации в однопроцессорных системах. Например, CLI используется в операционных системах для отключения прерываний, чтобы код ядра (обычно драйвер ) мог избегать состояний гонки в обработчике прерываний . Это необходимо при изменении нескольких связанных структур данных без прерывания.
STI набора инструкций x86 разрешает прерывания путем установки IF.
В некоторых реализациях инструкции, которая разрешает прерывания, прерывания не разрешаются до следующей инструкции. В этом случае последовательность разрешения прерываний, за которой сразу следует запрет прерываний, приводит к тому, что прерывания не распознаются.
Флаг прерывания влияет только на один процессор. В многопроцессорных системах обработчик прерываний должен использовать другие механизмы синхронизации, такие как блокировки .