任务切换的方法——《x86汇编语言:从实模式到保护模式》读书笔记37
任務切換的方法——《x86匯編語言:從實模式到保護模式》讀書筆記37
1. 中斷門和陷阱門
在實模式下,內存最低端的1M是中斷向量表,保存著256個中斷處理過程的段地址和偏移。當中斷發生時,處理器把中斷號乘以4,作為索引訪問中斷向量表,從相應的位置取出中斷處理過程的段地址和偏移地址,并轉移到哪里執行。具體過程可以參考我的博文
8086中斷系統——《x86匯編語言:從實模式到保護模式》讀書筆記04
在保護模式下,中斷向量表不再使用,取而代之的是中斷描述符表(Interrupt Descriptor Table,IDT)。不要害怕,它和GDT、LDT是一樣的,用于保存描述符。唯一不同的地方是,它保存的是門描述符,包括中斷門、陷阱門和任務門。
中斷門和陷阱門的格式如下圖:
當中斷發生時,處理器用中斷號乘以8(因為每個描述符占8個字節),作為索引訪問IDT,找到某個門描述符。如果是中斷門或陷阱門,那么就取出門描述符中的段選擇子和段內偏移量,然后轉移到相應的位置去執行。這個過程可以用下圖說明:
中斷門和陷阱門允許在任務內實施中斷處理,轉到全局空間執行一些系統級的管理工作。本質上,是任務內的控制轉移行為。
2. 通過中斷執行任務切換
但是,如果訪問IDT時遇到的是任務門,那么就會引發任務切換。即,要中斷當前任務的執行并保護現場,然后后切換到另一個任務去執行。
任務門的格式如下圖:
注意:任務門描述符可以安裝在IDT、GDT和LDT中。
通過中斷執行任務切換的過程,可以參考《Intel Architecture Software Developer’s Manual Volume 3:System Programming》的TASK SWITCHING這一節。
我把其中的關鍵點總結如下(序號不代表發生的先后順序):
1. 保存當前任務狀態到它的TSS(由TR寄存器指向)中;
2. 處理器訪問新任務的TSS,從中恢復現場;
3. TR寄存器指向新任務的TSS;
4. 把舊任務的TSS選擇子填寫到新任務TSS中的“任務鏈接域”,將新任務EFLAGS寄存器的NT位置1,同時還要把新任務TSS描述符的B位置1,表示該任務狀態為忙。(舊任務的TSS的B位不變,仍然為1.)
3. iret指令
當中斷發生時,可以執行常規的中斷處理過程,也可以執行任務切換。盡管性質不同,但是它們都要使用iret指令返回。前者是返回到同一任務內的斷點處;后者是返回到上一層任務。你也許會問:處理器如何區分這兩種截然不同的返回類型呢?
如下圖所示,32位的EFLAGS寄存器有一個NT位(bit14)—— 嵌套任務標志(Nested Task Flag).
每個任務的TSS中都有一個任務鏈接域,其內容可以是前一個任務的TSS描述符的選擇子。如果當前任務EFLAGS寄存器的NT位是1,則表示當前正在執行的任務嵌套于其他任務內,并且能夠通過TSS任務鏈接域的指針返回到前一個任務。
可以使用iret指令從當前任務返回(切換)到前一個任務,前提是當前任務的NT位必須是1.無論何時處理器遇到iret指令,它都要檢查NT位,如果是0,表明是一般中斷過程,則按照一般的中斷返回處理;如果是1,則表明當前任務之所以能夠執行,是因為它打斷了別的任務。因此,應當返回到原先被中斷的任務繼續執行,并且由處理器固件把當前任務EFLAGS的NT位改成0,并把TSS描述符的B位改成0.在保存了當前任務的狀態后,接著用被中斷的任務的TSS恢復現場。
4. 通過call或者jmp指令發起任務切換
在這兩種情況下,call指令或者jmp指令的操作數是任務的TSS描述符選擇子或者任務門。例如:
call 0x10:0x00000000jmp 0x10:0x00000000當處理器執行這兩條指令時,首先用選擇子索引GDT(對于本例,是GDT),分析得到的描述符類型
1. 對于代碼段描述符,就按照普通的段間轉移執行;
2. 對于調用門,按照調用門的規則執行;
3. 對于TSS描述符或者任務門(下圖中粉色部分),則執行任務切換。此時,指令中給出的32位偏移量被忽略,因為在執行任務切換時,所有處理器的狀態都可以從TSS中獲得。
使用CALL指令發起的任務切換類似于因中斷發起的任務切換。也就是說,由CALL指令發起的任務切換是“嵌套”的。如下圖所示:
5. 任務是不可重入的
執行任務切換時,新任務的狀態不能為忙。處理器是通過TSS描述符的B位來檢測是否重入的。由中斷、iret、call和jmp指令發起任務切換時,處理器固件會檢測新任務TSS描述符的B位,如果為1,則不允許執行這樣的切換。
6. 總結
處理器可以通過以下四種方法實施任務切換:
1. call指令或者jmp指令的操作數是GDT內的某個TSS描述符;
2. call指令或者jmp指令的操作數是GDT或者LDT內某個任務門描述符;
3. 一個異常或者中斷發生時,中斷號指向IDT內的某個任務門;
4. 在EFLAGS寄存器的NT位置位的情況下,當前任務執行了一個iret指令。
最后,把書上表格15-1再繪制一下,加深印象。
總結
以上是生活随笔為你收集整理的任务切换的方法——《x86汇编语言:从实模式到保护模式》读书笔记37的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 异常分类_Python异常
- 下一篇: 适合程序员的四大字体