陷阱(軟體中斷)
陷阱(trap)是真正把控制權從使用者程式帶進核心的機制——也就是穿過櫃員窗口的那個動作。如果系統呼叫是請求,陷阱就是遞送它的那個受控跳躍。這個字眼捕捉得很傳神:程式被刻意「捕捉」、抬離它正常的流程、安全地放進作業系統裡,稍後再送回去。因為它是由一條軟體指令刻意觸發的,所以又稱為軟體中斷。
順序如下。程式執行一條特殊的陷阱指令(不同晶片命名各異,但工作相同)。硬體同時做好幾件事:把模式位元切到核心、保存程式足夠的狀態(例如它執行到哪裡)以便日後恢復,並跳到一個固定的核心進入點,那個進入點記錄在核心開機時設好的一張表裡。核心接著處理起因——若是系統呼叫,就分派到正確的服務;它也用完全相同的陷阱機制處理同步錯誤,例如除以零、解參考一個壞位址,或分頁錯誤。完成後,核心執行一條「從陷阱返回」的指令,恢復先前保存的狀態,把模式位元翻回使用者,程式便繼續執行,彷彿它做的只是一次平常的呼叫。
陷阱值得與一般(硬體)中斷區分開來。陷阱是同步的——它由目前正在執行的指令引起(一次刻意的系統呼叫,或那條指令裡的錯誤),發生在可預測的位置。硬體中斷是非同步的——它由外部裝置引起(按了一個鍵、一個封包抵達),可能在任兩條指令之間發生。兩者都用同樣的基本管路切進核心,這也是為什麼有時統稱為「中斷」;關鍵差別在於起因是在執行中的程式內部(陷阱)還是外部(中斷)。
進入核心的兩種方式,都經由陷阱機制:你呼叫 write()——這是一次刻意的陷阱,進入核心去做輸入輸出;或者你的程式碼不慎除以零——CPU 就在那條指令上引發陷阱,由核心決定怎麼辦(通常是以錯誤終止程式)。
同一個受控跳躍,既處理刻意的系統呼叫,也處理非刻意的錯誤。
陷阱是同步的(由正在執行的指令引起);硬體中斷是非同步的(由外部裝置引起)。它們共用進入的機制,但混淆這兩種起因是初學者常犯的錯。