系統調用和中斷處理的異同(以Linux MIPS為例)


在Linux下寫一個驅動時候遇到的讀操作性能問題,讓我想一窺系統調用的處理流程,以查出問題的root cause。很多書把它和中斷處理放在一起講,但是又沒有哪本書說清楚了,看來只有代碼才能說明一切。以Linux系統下MIPS體系結構為例。

從開始說起。

1. 相關代碼

1 trap_init(void) /* 系統初始化:start_kernel中 */
2     set_handler(0x180, &except_vec3_generic, 0x80);/*          except_vec3_generic 根據cause寄存器跳轉到其若干類異常/中斷處理函數中*/
3     set_except_vector(0, rollback ? rollback_handle_int :     handle_int);
4     set_except_vector(1, handle_tlbm);
5         ... ...
6     set_except_vector(8, handle_sys);

當系統發現異常時,CPU將自動進入內核模式並禁止中斷,同時將PC指針指向默認的地址(根據異常的不同將分別進入偏移地址為0x180 or 0x200的地方,這些在函數trap_init都有體現,上述代碼沒有一一貼出)。

異常號為8時進入系統調用的處理入口。

1 /* 進入系統調用異常處理 */
2 handle_sys
3     SAVE_SOME
4     STI                 #  進入內核模式並enable中斷
5     la    t1, sys_call_table
6          ... ...

注意這里系統調用入口一開始就會enable中斷。

而異常號為0時進入中斷處理的入口。

 1 /* 進入中斷異常處理 */
 2 handle_int
 3     SAVE_ALL
 4     CLI                #  進入內核模式並disable中斷
 5    plat_irq_dispatch  # 每種類型的CPU都有自己的實現
 6         do_IRQ
 7             generic_handle_irq /*處理用戶注冊的ISR,關中斷進行 */
 8             irq_exit()
 9                 do_softirq   /*進入下半部處理(軟中斷) */
10                     local_irq_enable /*仍然在中斷上下文中,但是開中斷*/
11                     ... ... /*處理用戶注冊的下半部,
12 Note:有可能在softirq內核線程中進行處理,所以下半部的處理並不總是在中斷上下文中,但是下半部的思想就是允許中斷嵌套*/

上面的代碼描述了中斷處理的框架,簡要列出了處理中值得注意的地方。這里尤其注意中斷處理入口一開始直接disable中斷。

2. 結論

所以,系統調用和普通中斷處理的異同在於:兩者都是從同一個異常處理入口開始,但是系統調用會一開始讓CPU進入內核模式且使能中斷,然后從系統調用表中取得相應的注冊函數調用之;而中斷處理則讓CPU進入內核模式且disable中斷,繼而調用do_IRQ函數。所以系統調用的真實處理(系統調用表中的注冊函數執行)中可以阻塞,而中斷處理的上半部不可以。所以在寫驅動代碼如字符設備驅動,實現讀操作時是可以讓其sleep的(比如沒有數據時候,用戶設置讀模式是阻塞型的)。另一方面,如果該驅動讀操作過於耗時也是不可取的,它在內核態中執行,這個時候只有中斷的優先級比它高,其它的高優先級線程將不能得到及時調度執行。

另外,思考一下為什么在中斷的下半部如tasklet中不能做阻塞的操作,而系統調用卻可以?

首先,系統調用過程中阻塞意味着阻塞時(內核模式中)當前上下文放在當前線程棧中,同時系統調用所在線程狀態改變(比如調用wait_event),下次改線程再次被調度后就可以從阻塞點繼續run,這整個過程和一個普通線程阻塞並再次調度的過程是一樣的,唯一的區別在於系統調用的阻塞點是在內核模式下。而下半部則不一樣,作為中斷處理的一個例程邏輯上不屬於某個線程,所以它阻塞時第一不能改變當前線程的狀態(而wait_semaphore之類的函數則會),其次它在阻塞的情況下再次run的點是在被中斷線程再次被調度后,這也是不合理的,因為它不是該線程的一部分,憑什么讓它的運行時間受限於該線程的調度時機?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM