Linux中斷和系統調用的解析
系統調用和中斷的結構圖
作者:番茄味的可比克
鏈接:https://www.zhihu.com/question/30432536/answer/54998416
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。中斷:又稱為異步中斷,是其他硬件依照CPU時鍾信號隨機產生的。中斷又被分為可屏蔽硬件中斷和不可屏蔽中斷。在微機原理課程中,處理器中有兩個引腳NMI和INTR負責接受中斷信號,還有高級可編程中斷控制器(APIC),如8259A管理中斷信號。則可屏蔽硬件中斷:任何通過INTR或着局部APIC傳遞到處理器的中斷信號都被稱為可屏蔽硬件中斷,由IO設備產生的IRQ(Interrupt ReQuest)也是可屏蔽硬件中斷。但是通過INTR引腳傳遞的可屏蔽硬件中斷可使用Intel架構定義的中斷向量(0-255),而局部的APIC傳遞的部分只能使用16-255號向量。若中斷信號從NMI引腳傳遞過來,則發生的是一個不可屏蔽中斷。
像我們常見的,鍵盤、網卡輸入就是異步中斷,異步中斷(硬中斷)的處理我們在匯編語言中已經學過了
不可屏蔽中斷源一旦提出請求,cpu必須無條件響應,而對於可屏蔽中斷源的請求,cpu可以響應,也可以不響應。cpu一般設置兩根中斷請求輸入線:可屏蔽中斷請求INTR(Interrupt Require)和不可屏蔽中斷請求NMI(Nonmaskable Interrupt)。對於可屏蔽中斷,除了受本身的屏蔽位的控制外,還都要受一個總的控制,即CPU標志寄存器中的中斷允許標志位IF(Interrupt Flag)的控制,IF位為1,可以得到CPU的響應,否則,得不到響應。IF位可以有用戶控制,指令STI或Turbo c的Enable()函數,將IF位置1(開中斷),指令CLI或Turbo_c 的Disable()函數,將IF位清0(關中斷)。
典型的非屏蔽中斷源的例子是電源掉電,一旦出現,必須立即無條件地響應,否則進行其他任何工作都是沒有意義的。
典型的可屏蔽中斷源的例子是打印機中斷,CPU對打印機中斷請求的響應可以快一些,也可以慢一些,因為讓打印機等待兒是完全可以的。
————————————————
版權聲明:本文為CSDN博主「lidandan2016」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lidandan2016/java/article/details/53437273
異常:又稱為同步中斷,是當指令執行時CPU控制單元產生的,之所以稱為同步,是因為只有在一條指令終止執行后CPU才會發出中斷。在不失進程執行連續性的同時,按引起的異常的指令是否能重新執行,且依據它們被報告的方式,異常分為錯誤,陷阱,和終止三種情況。
錯誤:錯誤是一種通常可以能夠被修正的異常,一旦修正,程序能夠不失去連續性地接着執行。當報告錯誤發生時,處理器將機器狀態恢復到執行錯誤之前的狀態。錯誤處理例程的返回地址指向產生錯誤的指令,而不是錯誤指令之后的的那條指令。如頁錯誤。
陷阱:當引起陷阱的指令發生時,馬上產生該異常。陷阱允許程序不失去連續性的繼續執行。陷阱處理例程的返回地址指向引起陷阱的指令的下一條指令(與錯誤本質上的區別)。如溢出。
終止:它並不總是報告產生異常的指令的確定位置,也不允許引起終止的進程或任務重新執行。如總線錯誤導致異常終止。
Linux中的中斷向量:
0-19的中斷向量對應於異常和非屏蔽中斷。
20-31Intel保留
32-127可屏蔽硬件中斷
128用於系統調用的可編程異常
129-238可屏蔽硬件中斷
239本地APIC時鍾中斷
240本地APIC高溫中斷
241-250由Linux留作將來使用
251-253處理器間中斷
254本地APIC錯誤中斷
255本地APIC偽中斷(CPU屏蔽某個中斷時產生的)
軟中斷又叫做編程異常,主要用於執行系統調用即*int 0x80*以及給調試程序通報一個特定的事件,所以軟中斷是異常的一種,屬於同步中斷。
而我們的系統調用又是基於軟中斷實現的:注意,我說的是系統調用是基於軟中斷實現的,而不是說系統調用就是軟中斷!這一點看下面的系統調用原理就知道了
Linux中斷和系統調用過程
之后我們主要研究系統調用、其他異常和硬中斷,所以我們在以后就把硬中斷簡稱為中斷,也使用異常、系統調用以示區分
借助這副圖我們可以看到,用戶程序和內核之間的交互主要是通過系統調用實現的,而內核和外部設備之間主要是通過硬中斷
系統調用的執行過程
-
通過特定指令發出系統調用(int 0x80、sysenter、syscall)
這個int 0x80就是用於系統調用的可編程異常,當然這只是實現方法之一,由於通過中斷方式發起系統調用的性能較差,較新的CPU和內核都支持使用sysenter和syscall這兩條專用指令來發起系統調用。其中sysenter在32位系統中使用,對應的退出指令為sysexit;syscall在64位系統中使用,對應的退出指令為sysret。
-
CPU從用戶態切換到內核態,進行一些寄存器和環境設置
-
調用system_call內核函數,通過系統調用號在系統調用表中獲取對應的服務例程
-
調用系統調用處理例程
-
使用特定指令從系統調用返回用戶態(iret、sysexit、sysret)
可以看到,和硬件中斷不同,軟中斷基本上是由操作系統的內核處理的。而所有的系統調用也只使用了一個中斷向量
硬件中斷的執行過程
- 驅動設備將自己的中斷處理程序寫入內核,在加載內核的時候將中斷向量表初始化,中斷向量表中有驅動程序處理中斷的函數的中斷向量
中斷向量:是指中斷服務程序入口地址的偏移量與段基值,一個中斷向量占據4字節空間。中斷向量表是8088系統內存中最低端1K字節空間,它的作用就是按照中斷類型號從小到大的順序存儲對應的中斷向量,總共存儲256個中斷向量。在中斷響應過程中,CPU通過從接口電路獲取的中斷類型號(中斷向量號)計算對應中斷向量在表中的位置,並從中斷向量表中獲取中斷向量,將程序流程轉向中斷服務程序的入口地址。
-
CPU在指令周期的執行周期末進行檢測查看有無中斷,有中斷請求且可以處理時就進入中斷周期,開始做准備工作,保存斷點,確定中斷向量(中斷處理程序入口地址),然后置為PC,之后就又是取指、執行了。
-
底層的外部設備和計算機通信使用的就是中斷:硬件(比如說鍵盤按了一下)觸發了一個電信號,這個信號通過中斷線到達中斷控制器i8259A,i8259A接受到這個信號后,向CPU發送INT信號申請CPU來執行剛才的硬件操作,並且將中斷類型號也發給CPU
-
CPU中斷后去查中斷向量表,找到中斷服務例程,例程調用對應的設備驅動與外部設備之間通信
可以看到,硬件中斷中基本是CPU的工作,涉及到操作系統內核的部分很少
關於中斷向量的細節以及實現,可以看這篇文章:https://www.cnblogs.com/frankyou/p/8649435.html
Reference
- https://blog.csdn.net/weixin_41376979/article/details/83756975?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
- https://www.cnblogs.com/answercard/p/4288431.html
- https://www.zhihu.com/question/30432536
- https://blog.csdn.net/dillanzhou/java/article/details/82733562
- https://www.cnblogs.com/frankyou/p/8649435.html