1. 程式人生 > >作業系統的中斷處理

作業系統的中斷處理

/*

define SAVE_ALL "cld; \n\t"

"pushq  %rax;   \n\t"
"pushq  %rax;   \n\t"
"pushq  %es,    %rax;   \n\t"
"pushq  %rax;   \n\t"
"pushq"
...

上面的這段彙編程式碼的巨集定義就是在執行中斷程式的時候呼叫的現場保留的操作, 和異常的現場保留是類似的
不同的是, 在異常中是處理器產生的任務暫停, 而在中斷中是外部裝置產生的任務暫停
也和異常一樣, 在執行中斷處理函式之前就需要執行現場保留的程式碼
*/

/*

  • 執行的流程, 通過處理函式的入口函式, 先執行現場保留的程式碼,接著下來就和異常處理程式有一點不一樣了, 在中斷處理中, 呼叫一個do_IRQ函式, do_IRQ函式暫存器中的引數呼叫
  • 對應的處理函式, 在異常中, 我們通過處理函式的入口函式執行了現場保留的程式碼之後, 在呼叫明確的異常處理函式, 當然程式的返回地址都是要記錄的, 這樣才能返回我們原來的程式
    */

/*

  • 上面講到的是在遇到了異常的時候CPU是怎麼處理的, 前提是我們現在為中斷提供了入口函式 --> 注意: 入口函式和程式處理函式不是完全一樣的, 入口函式中包含有程式處理函式,
  • 在入口函式中呼叫程式處理函式, 在異常和中斷中都是這樣的, 只不過正如上面提到的那樣, 在中斷中的程式處理函式都是交給了一個do_IRQ函式通過引數判斷要呼叫對應的中斷處理函式
  • 我們現在就是要使用set_intr_gate函式將中斷的入口函式們一一註冊好, 注意: 這裡的set_intr_gate函式雖然接受的引數是我們入口函式的地址, 但是他在中斷向量表對應的index
  • 寫入的資料是一個門描述符, 該門描述符不僅僅是簡單的是入口函式的地址在Linux中, 有一個函式指標陣列, 在該陣列中儲存這的就是所有的中斷處理函式的入口函式的地址, 也就是
  • 函式指標, 需要注意的是, 我們使用for迴圈進行註冊的時候, 起始的i是應該為32, 因為前32箇中斷向量號已經被異常時候, 但是有不是32個異常, 用到的是20個異常, 剩下的12個異常中斷
  • 向量號為Intel所保留
    */

/*

  • 註冊好了之後, 我們需要初始化好ICW和OCW暫存器中的資料
  • */

/*

  • 下面是一個do_IRQ的demo示例
  • 功能: 在螢幕上打印出時鐘中斷的中斷向量號
    */

void do_IRQ(unsigned long regs, unsigned long nr) {
color_printk(RED, BLACK, "do_IRQ:%#08x\t", nr);
io_out(0x20, 0x20);
}

/*

  • 通過閱讀建議的鍵盤驅動, 發現所以的驅動編寫就是在編寫一箇中斷處理函式, 我們已經知道了, CPU根據中斷向量表中的index找到鍵盤中斷的入口函式, 在該入口函式中呼叫do_IRQ函式, 在
  • do_IRQ函式中呼叫驅動程式, 就是這樣而已, 所以編寫驅動程式僅僅是核心中的冰山一角
    */