首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Windows 即時中斷程式設計:DPMI 介面實作硬體中斷處理完整指南

     編輯:關於C++

前言:Windows 訊息機制與即時回應的矛盾

Windows 3.x/9x 採用非搶佔式協同多工,訊息驅動架構導致外部硬體事件必須經過系統訊息佇列 → 應用程式訊息佇列 → 視窗程序的漫長路徑,無法滿足工業控制、資料擷取等即時應用的硬性延遲需求。雖可購買即時核心 (如 FLX、iRMX),但中小專案成本過高。本文展示如何利用 DPMI (DOS Protected Mode Interface) 在 Windows 增強模式下直接掛接硬體中斷向量,繞過訊息機制實現微秒級回應。

Windows 保護模式與中斷機制回顧

實模式中斷 (IVT)

  • 中斷向量表固定在 0000:0000,1024 位元組,256 條目,每項 4 位元組 (CS:IP)
  • CPU 自動壓入 FLAGS、CS、IP,查 IVT 跳轉
  • IRET 返回

保護模式中斷 (IDT)

  • 中斷描述符表 (IDT) 位置由 IDTR 暫存器指定,可移動
  • 每個描述符 8 位元組,含 32 位元組線性基址、段選擇子、DPL、類型等
  • Windows 建立自有 IDT,應用程式不直接使用 IVT
  • IVT 仍存在但含義改變,由 Windows/VxD 管理

DPMI 介面:保護模式應用程式的橋樑

DPMI 由 INT 31h 與部分 INT 2Fh 服務組成,Windows 作為 DPMI Host 提供服務。關鍵中斷管理功能:

INT 31h AH=0204h - 取得保護模式中斷向量

輸入:  AX=0204h, BL=中斷號
輸出:  CF=0 成功, CX:DX = 選擇子:偏移量
       CF=1 失敗

INT 31h AH=0205h - 設定保護模式中斷向量

輸入:  AX=0205h, BL=中斷號, CX:DX = 處理程式選擇子:偏移量
輸出:  CF=0 成功, CF=1 失敗

時機關鍵

  • 掛接:主視窗 WM_CREATE 訊息處理中 (最早安全時機)
  • 恢復:主視窗 WM_DESTROY 訊息處理中 (必須恢復,否則 Windows 崩潰)
  • 恢復策略:先用 0204h 保存原向量,退出時用 0205h 還原

完整實作範例:COM1 非同步接收中斷 (IRQ4)

中斷服務程式 (ISR)

void interrupt far DataReceive() {
    static int i = 0;
    char ch = inportb(0x3F8);  // 讀取接收緩衝器
    if (!inFlag) {
        if (ch != 's' && i == 0) goto ExitISR; // 等待起始字元 's'
        dataCom_r[i++] = ch;
        if (ch == 'e') { inFlag = 1; i = 0; } // 結束字元 'e'
    }
ExitISR:
    outportb(0x20, 0x20); // 發送 EOI 給主 8259A
}

初始化與掛接

void InitCom(void) {
    // 1. 保存原中斷向量 (IRQ4 = INT 0Ch)
    _asm {
        cli
        mov ax, 0204h
        mov bl, 0Ch
        int 31h
        sti
    }
    old_vector = MK_FP(_CX, _DX);

    // 2. 設定新中斷向量指向 DataReceive
    _asm {
        cli
        mov ax, 0205h
        mov bl, 0Ch
        mov cx, seg DataReceive
        mov dx, offset DataReceive
        int 31h
        sti
    }

    // 3. 硬體初始化:8250 UART + 8259A PIC
    unsigned char s8259 = inportb(0x21);        // 保存主 PIC IMR
    outportb(0x21, s8259 & 0xE8);               // 開啟 IRQ4 (bit 3=0)
    outportb(0x3FB, 0x83);  // DLAB=1
    outportb(0x3F8, 0x0C);  // 鮑率 9600: 除數低位
    outportb(0x3F9, 0x00);  // 除數高位
    outportb(0x3FB, 0x03);  // DLAB=0, 8N1
    outportb(0x3FC, 0x08);  // 啟用接收中斷 (IER bit 0)
    outportb(0x3F9, 0x01);  // 輔助控制
}

清理與恢復

void RestoreComm(void) {
    outportb(0x21, s8259); // 恢復 PIC IMR
    _asm {
        cli
        mov ax, 0205h
        mov bl, 0Ch
        mov cx, seg old_vector
        mov dx, offset old_vector
        int 31h
        sti
    }
}

視窗程式整合

// WM_CREATE
case WM_CREATE:
    InitCom();
    break;

// WM_DESTROY
case WM_DESTROY:
    RestoreComm();
    PostQuitMessage(0);
    break;

// 主迴圈中檢查全域旗標 inFlag,讀取 dataCom_r 緩衝區處理資料

關鍵技術細節與避坑指南

1. 中斷號對應

IRQ中斷號裝置
IRQ008h定時器
IRQ109h鍵盤
IRQ30BhCOM2/COM4
IRQ40ChCOM1/COM3
IRQ50DhLPT2/聲卡
IRQ70FhLPT1

2. 8259A PIC 程式設計

  • IMR (0x21):中斷屏蔽暫存器,對應 bit 置 1 為屏蔽
  • EOI (0x20):結束中斷命令,非特定 EOI 為 0x20
  • 主從片級聯需處理從片 EOI (0xA0)

3. 8250/16550 UART 關鍵埠

埠位址功能 (DLAB=0)功能 (DLAB=1)
Base+0 (0x3F8)接收/發送緩衝器 (RBR/THR)除數鎖存器低位 (DLL)
Base+1 (0x3F9)中斷啟用 (IER)除數鎖存器高位 (DLH)
Base+2 (0x3FA)中斷識別 (IIR, 唯讀)-
Base+3 (0x3FB)線路控制 (LCR)-
Base+4 (0x3FC)調制解調器控制 (MCR)-
Base+5 (0x3FD)線路狀態 (LSR)-
Base+6 (0x3FE)調制解調器狀態 (MSR)-
Base+7 (0x3FF)暫存器 (SCR)-

4. CLI/STI 必須成對使用

在修改中斷向量、操作 PIC/UART 暫存器時,必須 cli 關閉中斷,操作完成後 sti 開啟,防止競態條件。

5. 中斷服務程式規範

  • 盡可能短小、快速,避免呼叫 DOS/BIOS/Windows API
  • 只做資料搬移、旗標設置、硬體確認
  • 複雜處理延遲到主程式迴圈 (透過全域旗標/緩衝區)
  • 必須發送 EOI,否則 PIC 不會遞送同優先級後續中斷
  • 保護所有使用的暫存器 (編譯器通常自動處理 interrupt 關鍵字函式)

實測驗證與效能

在 Windows 3.1 上同時運行:

  • 伺服器端:即時串口通訊 + 多個網路資料子服務
  • 客戶端應用程式
  • FoxPro 資料庫系統

結果:系統穩定運行,串口中斷回應延遲在微秒級,明顯優於訊息機制。遷移至 Windows 95 同樣正常運作。

現代視角:為什麼今天不再這樣做?

  • Windows NT 核心 (2000/XP/現代):完全禁止使用者模式程式碼操作硬體、修改 IDT、執行 CLI/STI、存取 I/O 埠。必須編寫核心模式驅動程式 (KMDF/WDM)。
  • 用戶模式驅動程式架構 (UMDF):現代替代方案,在用戶模式處理裝置邏輯,核心模式僅處理中斷分派與 I/O 緩衝。
  • 虛擬化/隔離:現代 OS 嚴格隔離硬體存取,DPMI 介面已不再支援。

總結

本文展示的 DPMI 中斷掛接技術,是 Windows 3.x/9x 時代實現硬體即時回應的經典方案。透過 INT 31h AH=0204h/0205h 管理保護模式中斷向量、CLI/STI 保護關鍵區段、正確程式化 8259A PIC 與 8250 UART、在 WM_CREATE/WM_DESTROY 管理生命週期,可在視窗應用程式中獲得微秒級硬體中斷回應。雖然現代 Windows 架構已使此技術失效,但其核心思想——繞過 OS 排程器直接處理硬體事件——仍是理解即時系統、驅動程式開發、嵌入式韌體設計的基礎知識。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved