www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 公眾號精選 > IOT物聯(lián)網小鎮(zhèn)
[導讀]作?者:道哥,10年的嵌入式開發(fā)老兵。專注于:C/C、Linux操作系統(tǒng)、應用程序設計、物聯(lián)網、單片機和嵌入式開發(fā)等領域。公眾號回復【書籍】,獲取Linux、嵌入式領域經典書籍。轉?載:歡迎轉載文章,轉載需注明出處。中斷向量與中斷描述符中斷的分類內部中斷外部中斷中斷號中斷向量和中...

作  者:道哥,10 年的嵌入式開發(fā)老兵。


專注于:C/C 、Linux操作系統(tǒng)、應用程序設計、物聯(lián)網、單片機和嵌入式開發(fā)等領域。公眾號回復【書籍】,獲取 Linux、嵌入式領域經典書籍。


轉  載:歡迎轉載文章,轉載需注明出處。


  • 中斷向量與中斷描述符


  • 中斷的分類


    • 內部中斷


    • 外部中斷


  • 中斷號


  • 中斷向量和中斷處理程序


    • 中斷向量的本質


    • 中斷處理程序的安裝


  • 中斷現(xiàn)場的保護和恢復


  • 總結:中斷的本質


在軟件開發(fā)中,中斷是一個繞不開的重要話題,但是,不知道您是否遇到過這樣的困惑


很多書籍、文章在介紹中斷相關的知識點時,說的都挺有道理。


這篇文章對中斷的講解很正確,那篇文章在描述中斷的時候也挺對的,但是,這兩篇文章中,怎么有些內容是矛盾的???!


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?單獨看任何一篇文章感覺都有道理,看的越多,反而越迷糊?


好比在森林里迷路了,如果只有一個指南針,肯定能走出來。


但是,如果你有2個指南針,所指的方向卻是相反的,這個時候應該相信誰呢?!


我們仔細梳理了一下就會發(fā)現(xiàn):每一篇文章都是在一定的語境、一定的上下文環(huán)境中來講解的,不同文章的矛盾之處,恰恰是它們所描述的那個上下文大環(huán)境不同。


上下文環(huán)境,就是描述當前正在執(zhí)行的程序相關的靜態(tài)信息,比如:有哪些代碼段,??臻g在哪里,進程描述信息在什么位置,當前執(zhí)行到哪一條指令等等。


如果我們沒有一個全局的視角,在同一個上下文環(huán)境中來對比不同的文章,就會讓自己的理解和認識越來越蒙圈。


因此,對于這種概念比較龐雜,無法用某種確定的邏輯來貫穿的知識點,在腦袋中一定要有一幅全局的地圖。


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?只有對這個全局的地圖掌握了,在具體學習每一個局部的知識點時,才能知道自己所處的位置在哪里,才不至于走偏。


這篇文章,我們繼續(xù)去繁從簡,從8086這個最簡單的處理器入手,來聊一下關于中斷的一些知識。


有了這個儲備,理清了基本的脈絡之后,以后再去學習Linux系統(tǒng)中的中斷相關內容時,才會有原來如此的感覺!


中斷向量與中斷描述符

中斷向量這個詞很時髦,也很神秘!


按道理,不應該在第一部分就端上中斷向量這盤硬菜,應該從中斷源開始聊起。


但是,畢竟我們已經學習過那么多關于中斷的知識了,腦袋中肯定是對中斷已經有了一些的基本認知。


所以,在這里我們還是首先來明確一下中斷向量中斷描述符這個問題。


在前面的文章中已經聊過關于實模式和保護模式的問題,在 【Linux 從頭學】這個系列中,我們一直以來描述的都是實模式下的事情。


本文是實模式下的最后一篇文章,下一篇文章將會進入保護模式。


那么,中斷向量就是工作在實模式下的,處理器通過中斷號和中斷向量,來定位到相應的中斷處理程序。


中斷描述符呢,就是工作在保護模式下,處理器通過中斷號和中斷描述符,來定位到相應的中斷處理程序。


也就是說:中斷向量和中斷描述符,它倆的根本作用是一樣的


只是它們存在于不同的大環(huán)境中,而且從描述上也能感覺到,保護模式下的中斷描述符會更復雜一些,功能也更強大一些。


它倆就像一對兄弟一樣,從外表上看是差不多,功能也是類似。但是透入到內部去看,就會發(fā)現(xiàn)有很多的不同之處。


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?因此,這篇文章我們講解的就是在實模式下的中斷,這一點請大家先明白。


中斷的分類

在x86系統(tǒng)中,中斷的分類如下:


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?

內部中斷

所謂的內部中斷,是在CPU內部產生并進行處理的。比如:


  1. CPU 遇到一條除以 0 的指令時,將產生 0 號中斷,并調用相應的中斷處理程序;


  2. CPU 遇到一條不存在的非法指令時,將產生 6 號中斷,并調用相應的中斷處理程序;


對于內部中斷,有時候也稱之為異常。


軟中斷也屬于內部中斷,是非常有用的,它是由int指令觸發(fā)的。比如int3這條指令,gdb就是利用它來實現(xiàn)對應用程序的調試。


很久之前寫過這樣的一篇文章原來gdb的底層調試原理這么簡單,其中就描述了gdb是如何通過插入一個int指令,來替換被調試程序的指令碼,從而實現(xiàn)斷點調試功能的。


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?

外部中斷

x86CPU上有2個中斷引腳:INT和INTR,分別對應:不可屏蔽中斷和可屏蔽中斷


所謂不可屏蔽,就是說:中斷不可以被忽視,CPU必須處理這個中斷。


如果不處理,程序就沒法繼續(xù)執(zhí)行。


而對于可屏蔽中斷,CPU可以忽略它不執(zhí)行,因為這類中斷不會對系統(tǒng)的執(zhí)行造成致命的影響。


對于外部的可屏蔽中斷,CPU上只有一根INTR引腳,但是需要產生中斷信號的設備那么多,如何對眾多的中斷信號進行區(qū)分呢?


一般都是通過可編程中斷控制器(Programmable Interrupt Controller, PIC),在計算機中使用最多的就是8259a芯片。


雖然現(xiàn)代計算機都已經是APIC(高級可編程中斷控制器) 了,但是由于8259a芯片是那么的經典,大部分描述外部中斷的文章都會用它來舉例。


每一片8259a可以提供8個中斷輸入引腳,兩片芯片級聯(lián)在一起,就可以提供15個中斷信號:


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?
  1. 主片的輸出引腳 INT 連接到 CPU 的 INTR 引腳上;


  2. 從片的輸出引腳 INT 連接到主片的引腳 2 上;


這樣的話,兩片8259a芯片就可以向CPU提供15個中斷信號了,比如:鼠標、鍵盤、串口、硬盤等等外設。


1. 8259a 之所以稱作可編程,是因為它的內部有相關的寄存器。


2. 可以通過指定的端口號,對這些寄存器進行設置,讓 8 根 IRQ 中斷線上的信號,在送到 CPU 時,對應不同的中斷號。


另外,對于外部可屏蔽中斷,有2層的屏蔽機制:


  1. 在 8259 芯片中,有中斷屏蔽寄存器,可以對 IRQ0 ~ IRQ7 輸入引腳進行屏蔽;


  2. 在 CPU 內部,也有一個標志寄存器,可以對某一類中斷信號進行屏蔽;


中斷號

在x86處理器中,一共支持256個中斷,每一個中斷都分配了一個中斷號,從0到255。


其中,0 ~ 31號中斷向量被保留,用來處理異常和非屏蔽中斷(其中只有2號向量用于非屏蔽中斷,其余全部是異常)。


當BIOS或者操作系統(tǒng)提供了異常處理程序之后,當一個異常產生時,就會通過中斷向量表找到響應的異常處理程序,查找的過程馬上就會介紹到。


從中斷號32開始,全部分配給外部中斷


比如:


1. 系統(tǒng)定時器中斷 IRQ0,分配的就是 32 號中斷;


2. Linux 的系統(tǒng)調用,分配的就是 128 號中斷;


我們來分別看一下內部中斷和外部中斷相關的中斷號:


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?對于通過8259a可編程中斷控制器接入的中斷信號分配如下圖所示:


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?剛才已經說過,8259a是可編程的,假如我們通過配置寄存器,把IRQ0的中斷號設置為32, 那么主片上IRQ1 ~ IRQ7所對應的中斷號依次加1,從片上IRQ8~IRQ15對應的中斷號也是依次遞增。


所以,有時候我們可以在代碼中斷看到下面的宏定義:


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?

中斷向量和中斷處理程序

當一個中斷發(fā)生的時候,CPU獲取到該中斷對應的中斷號,下一步就是要確定調用哪一個函數(shù)來處理這個中斷,這個函數(shù)就稱作中斷服務程序(Interrupt Service Routine,ISR),有時候也稱作中斷處理程序、中斷處理函數(shù),本質都一樣。


中斷向,就是通過中斷號去查找處理程序的重要的橋梁!


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?

中斷向量的本質

在8086中,一個中斷向量,就是一個 段地址:中斷處理函數(shù)偏移量 這樣的一對數(shù)據(jù),通過這個數(shù)據(jù),就可以定位到內存中指定位置的那個中斷處理函數(shù)。


非常類似于高級編程語言中的函數(shù)指針,就是用來指向一個函數(shù)的開始地址。


8086規(guī)定:256個中斷向量,必須從內存的0地址處開始存放。


每一個中斷向量占用4個字節(jié)(2個字節(jié)的地址,2個字節(jié)的偏移地址),256個中斷一共占用了1024個字節(jié)的空間。


之前的文章中,已經介紹過相關的內存模型,如下圖所示:


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?如果把一個中斷向量看作函數(shù)指針,那么這個中斷向量就相當于是函數(shù)指針數(shù)組


舉例:


假設2號中斷被觸發(fā)了,CPU就會到中斷向量表中查找2號中斷的中斷向量。


因為每一個中斷向量占據(jù)4個字節(jié),那么2號中斷向量的開始地址就是2 * 4 = 8,第8個字節(jié)。


然后在第8個字節(jié)開始,取4個字節(jié)的內容:0x1000:0x2000。


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?意思是:2號中斷的處理函數(shù),在段地址為 0x1000,偏移量為 0x2000 的位置處。


那么CPU就按照8086的物理地址計算方式,得到中斷處理函數(shù)的物理地址為0x12000(段地址左移4位 偏移地址),于是就跳轉到該函數(shù)地址處去執(zhí)行。


1. 由于 Linux 系統(tǒng)是運行在保護模式,在這個模式下,當發(fā)生中斷時,是通過中斷描述符來查找中斷處理函數(shù)的。


2. 每一個中斷描述符,描述了一個中斷處理函數(shù)所在段的選擇子和偏移量,本質上也是用來查找一個中斷處理函數(shù)。


中斷處理程序的安裝

既然通過中斷向量,找到了中斷處理程序,那么這些中斷處理程序都是誰放在內存中的呢


如果您看過一些比較底層的計算機書籍,就能看到一般都會舉例:如何手動的把一個普通函數(shù)設置為一個中斷處理函數(shù)。


操作步驟是:


  1. 在代碼中,寫一個普通函數(shù);


  2. 把這個函數(shù)的指令碼,搬運到內存中的某一個位置;


  3. 把這個位置(段地址:偏移量),作為一個中斷向量,設置到中斷向量表中;


此時,如果發(fā)生了該中斷,你所提供的函數(shù)就作為中斷處理函數(shù)被執(zhí)行了。


當然了,在一個計算機系統(tǒng)中,BIOS、操作系統(tǒng)和各種外設,會自動為我們提供很多基本的中斷處理函數(shù)的。


比如:BIOS中就提供了軟中斷、內部中斷、硬件中斷等處理函數(shù),這些函數(shù)是固化在BIOS的代碼中的(映射到BIOS所在的ROM芯片上),BIOS只需要把這些處理函數(shù)的地址,寫入到中斷向量表中的相應位置即可。


在之前的文章中提到過,內存中的某些位置是映射到外設的ROM,在這些外設的ROM中也存在一些外設自帶的程序。


BIOS在啟動時,會掃描這些映射到外設的內存空間,通過某些關鍵字信息,如果發(fā)現(xiàn)外設有自帶的程序,就會去執(zhí)行。


這些外設程序一般是進行一些自身的初始化,并填寫相關的中斷向量表,使它們指向外設自帶的中斷處理程序。


對于操作系統(tǒng)來說就更不用說了,它會重新安排自己需要的中斷處理函數(shù),這部分內容我們以后再一起學習、討論!


Linux從頭學07:【中斷】那么重要,它的本質到底是什么?

中斷現(xiàn)場的保護和恢復

當一個中斷發(fā)生的時候,肯定有一個正在執(zhí)行的程序被打斷。


當中斷處理函數(shù)執(zhí)行結束之后,這個被打斷的程序需要從剛才被打斷的地方繼續(xù)執(zhí)行(暫時先不要考慮從中斷返回點,進行多任務切換的事情)。


而一個程序執(zhí)行的上下文環(huán)境,就是處理器中的各種寄存器內容:代碼段寄存器cs,指令指針寄存器sp,標志寄存器FLAGS。


但是,在中斷處理程序中,也需要使用這些寄存器。


處理器中的這些寄存器,就是每一個程序執(zhí)行時上下文信息的存儲容器,當然也包括終端處理程序!


因此,在進入中斷處理程序之前,CPU會自動的把這些寄存器push到棧中保存起來,然后再跳轉到中斷處理程序中去執(zhí)行。


當中斷處理程序執(zhí)行結束后,CPU會從棧中彈出這些內容,恢復到相應的寄存器中,于是被打斷的程序就可以繼續(xù)執(zhí)行了。


總結:中斷的本質

從功能的角度看,中斷有2個作用:


  1. 提供執(zhí)行異步序列的機制;


  2. 給應用程序提供進入系統(tǒng)層的入口;


關于第2點,以后在介紹到Linux中的int 0x80中斷就非常清楚了,也就是通過中斷,讓應用層的程序有機會進入到系統(tǒng)代碼中去執(zhí)行。


因為應用層與操作系統(tǒng)層的代碼,是工作在不同的安全級別


為了系統(tǒng)的安全,Linux操作系統(tǒng)提供了這樣的一個機制,讓低安全級別的應用程序,進入到高安全級別的操作系統(tǒng)代碼中去執(zhí)行,畢竟所有的硬件等系統(tǒng)資源都是由操作系統(tǒng)來統(tǒng)一管理的。


我們再從中斷處理程序的安裝角度來看,中斷本質上就是增加了一層間接性:通過固定位置的中斷向量表,讓中斷處理函數(shù)的實際地址可以被動態(tài)的放在任意位置。


為什么這么做?


假如操作系統(tǒng)想為某一個中斷提供處理函數(shù),那么這個處理函數(shù)的地址放在內存中的什么位置比較合適?


需要考慮CPU, 內存大小和布局等多種因素,非常復雜!


而通過使用中斷向量表,就在一個固定位置處存放了很多個“指針”


當中斷處理函數(shù)放在內存中某個任意位置之后,讓“指針”指向這個函數(shù)的地址就可以了,從而達到解耦的目的。


這樣的話,無論是發(fā)生硬件中斷,還是應用層代碼通過中斷門來調用操作系統(tǒng)提供的函數(shù),只要觸發(fā)相應的中斷就可以了,簡化了CPU的設計。



------ End ------
關于中斷的相關內容,還有很多需要學習,任重而道遠


特別是在Linux系統(tǒng)中,中斷處理又分為上半部分、下半部分,而下半部分又可以根據(jù)不同的功能需求采取不同的機制來處理。


我仍然是持有之前的觀點:磨刀不誤砍柴工。


把學習周期拉長,一點一滴的積累,Haste Makes Waste!


本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
關閉
關閉