Linux從頭學(xué):一文理解【任務(wù)管理】和【任務(wù)切換】
LDT:局部描述符表
TSS: 任務(wù)狀態(tài)段
TCB: 任務(wù)控制塊
x86 系統(tǒng)中的保護(hù)模式,給系統(tǒng)的安全性提供了很大的保障,但是在我們之前的文章中,一直都淡化了特權(quán)級(jí)別這個(gè)概念。
例如:在保護(hù)模式下的段選擇器,我們一直都只把它看做一個(gè)段描述符的"索引號(hào)",用來(lái)在 GDT (全局描述描述符表) 中查找一個(gè)段描述符,例如:
圖中:代碼段寄存器中的索引號(hào)是 4 ,GDT 中每一個(gè)表項(xiàng)占用 4 個(gè)字節(jié),于是就在偏移量為 16 的位置,找到了代碼段的描述符,進(jìn)而從描述符中找到代碼段的起始地址和長(zhǎng)度界限。
數(shù)據(jù)段、棧段的操作過(guò)程也是這樣的。
從現(xiàn)在開(kāi)始,我們需要讓用戶程序擁有自己私有的描述符表 LDT(Local Descriptor Table),并且擁有自己的特權(quán)級(jí)別(總不能讓用戶程序與操作系統(tǒng)一樣,工作在非常高的 0 特權(quán)級(jí)別)。
因此,我們需要糾正之前的錯(cuò)誤:段寄存器中,不僅僅有段的索引號(hào),還有另外兩個(gè)屬性:TI 和 RPL,如下圖所示:
TI 標(biāo)志位:表示到哪個(gè)表中(GDT or LDT)查找描述符;
TI = 0: 到 GDT 中查找描述符;
TI = 1: 到 LDT 中查找描述符;
RPL(Request Privilege Level) 標(biāo)志位:表示想給段寄存器賦值的請(qǐng)求者(也就是一段代碼),它的特權(quán)級(jí)別;
此時(shí),繼續(xù)把段寄存器中的內(nèi)容稱作段索引符就不合適了,一般稱作:選擇子。
LDT:局部描述符表
在上一篇文章中,操作系統(tǒng)把應(yīng)用程序從硬盤讀取到內(nèi)存中之后,為應(yīng)用程序創(chuàng)建了三個(gè)段描述符,這三個(gè)段描述符都放在了 GDT 表中,這是不合理的。
首先,在多任務(wù)系統(tǒng)中,應(yīng)用程序的數(shù)量是不確定的,應(yīng)用程序也會(huì)執(zhí)行結(jié)束。
如果把所有應(yīng)用程序的段描述符都放在 GDT 中,對(duì)于操作系統(tǒng)來(lái)說(shuō),管理這個(gè)數(shù)據(jù)太復(fù)雜。
其次,當(dāng)引入特權(quán)級(jí)別之后,如果應(yīng)用程序的段描述符放在 GDT 中,那么就意味著應(yīng)用程序需要有權(quán)限來(lái)訪問(wèn) GDT,而 x86 系統(tǒng)中只有一個(gè) GDT(所以叫做 Global Description Table),只能被操作系統(tǒng)訪問(wèn)。
因此,操作系統(tǒng)需要為每一個(gè)應(yīng)用程序,單獨(dú)申請(qǐng)一塊空間,用作這個(gè)程序自己的段描述附表,稱作:LDT(Local Description Table)。
例如:現(xiàn)在系統(tǒng)中有 2 個(gè)用戶程序: APP1 和 APP2,操作系統(tǒng)在加載每一個(gè)應(yīng)用程序的時(shí)候,就會(huì)在應(yīng)用程序自己的內(nèi)存空間中,申請(qǐng)一塊,用作 LDT:
為什么是 “應(yīng)用程序自己的內(nèi)存空間”?
因?yàn)槊恳粋(gè)應(yīng)用程序,都獨(dú)享 4G 大小的虛擬內(nèi)存空間。
在 LDT 中,存放著當(dāng)前應(yīng)用程序自己的段描述符信息,例如:代碼段、數(shù)據(jù)段、棧段。
LDT 所占用的空間也屬于內(nèi)存的一部分,有起始地址和長(zhǎng)度界限,因此也需要為它創(chuàng)建一個(gè)段描述符,這個(gè)描述符就放在 GDT 中。
在 Linux 應(yīng)用層,我們會(huì)嚴(yán)格的區(qū)分進(jìn)程、線程,但是在系統(tǒng)的底層,這樣的區(qū)分界限已經(jīng)比較模糊了,用任務(wù) task 來(lái)稱呼更通用些。
根據(jù)剛才的假設(shè),現(xiàn)在系統(tǒng)中有 2 個(gè)用戶程序,那么處理器怎么知道:當(dāng)前正在執(zhí)行的是哪一個(gè)應(yīng)用程序的 LDT 中的代碼?
正如處理器中有一個(gè)寄存器 GDTR,保存著 GDT 的開(kāi)始地址和長(zhǎng)度,處理器中還有一個(gè)寄存器 LDTR,存儲(chǔ)著當(dāng)前正在執(zhí)行的那個(gè)應(yīng)用程序的 LDT 開(kāi)始地址和長(zhǎng)度:
所有應(yīng)用程序的虛擬內(nèi)存的高端地址部分,映射的都是操作系統(tǒng)的內(nèi)存空間,按照 Linux 中的做法,3G ~ 4G 空間被操作系統(tǒng)使用。
圖中的綠色部分,表示操作系統(tǒng)空間(1G),在分頁(yè)機(jī)制下,它們都映射到相同的物理內(nèi)存頁(yè)上(藍(lán)色虛線箭頭)。
當(dāng)操作系統(tǒng)切換到應(yīng)用程序2時(shí),處理器中的 LDTR 就會(huì)被賦值為應(yīng)用程序2 的 LDT 的線性地址和長(zhǎng)度信息。
GDTR 中的內(nèi)容不變,因?yàn)槊總(gè)應(yīng)用程序中的 GDT 都是從操作系統(tǒng)“繼承”而來(lái)的,開(kāi)始地址和長(zhǎng)度都是一樣的。
TSS: 任務(wù)狀態(tài)段
顧名思義,任務(wù)狀態(tài)段就是用來(lái)存儲(chǔ)和恢復(fù)任務(wù)的狀態(tài)信息。
經(jīng)常聽(tīng)到一個(gè)術(shù)語(yǔ):任務(wù)上下文。
所謂的上下文,就是體現(xiàn)一個(gè)任務(wù)正在被執(zhí)行時(shí)的環(huán)境信息,主要就是處理器中的各種寄存器內(nèi)容,也就是下面這張圖中的寄存器們:
這張圖反映了一個(gè)任務(wù)上下文的所有寄存器信息。
當(dāng)任務(wù)被調(diào)度器中止執(zhí)行之前,需要把這些寄存器中的值都保存下來(lái),相當(dāng)于做一個(gè)快照。
當(dāng)這個(gè)任務(wù)以后又被恢復(fù)執(zhí)行時(shí),再把這個(gè)快照中保存的信息,原樣的賦值給圖中的所有寄存器,這樣就稱作恢復(fù)任務(wù)上下文,這個(gè)任務(wù)就從上次被中止的地方繼續(xù)執(zhí)行(因?yàn)橹噶钪羔樇拇嫫?EIP 被恢復(fù)了)。
就如同 LDT 一樣,TSS 也是操作系統(tǒng)為應(yīng)用程序分配的一塊內(nèi)存空間,只不過(guò)這塊空間是位于操作系統(tǒng)的勢(shì)力范圍內(nèi),只能由操作系統(tǒng)來(lái)操作。
TSS 也有起始地址和長(zhǎng)度界限,也需要為它在 GDT 中創(chuàng)建一個(gè)段描述符。
與 LDT 類似,在處理器中也有一個(gè)寄存器 TR,用來(lái)指向當(dāng)前正在執(zhí)行的那個(gè)任務(wù)的 TSS。
當(dāng)進(jìn)行任務(wù)切換的時(shí)候:
首先,把處理器中的寄存器內(nèi)容,存儲(chǔ)到 TR 寄存器指向的 TSS 段中(即將被停止的任務(wù));
然后,把新的任務(wù)的 TSS 段中的內(nèi)容,復(fù)制到處理器的各寄存器中,并且把 TSS 地址賦值給 TR 寄存器;
TCB: 任務(wù)控制塊
任務(wù)控制塊,可以說(shuō)是系統(tǒng)中用來(lái)管理任務(wù)的最重要的數(shù)據(jù)結(jié)構(gòu)了,操作系統(tǒng)用來(lái)管理任務(wù)的所有信息都可以放在這里。
看一下 Linux 2.6 內(nèi)核代碼中的結(jié)構(gòu)體:struct task_struct{ ... },就知道 TCB 有多復(fù)雜了,有些書籍上也稱之為 PCB(Process Control Block,進(jìn)程控制塊)。
在這個(gè)結(jié)構(gòu)中,一些常用的信息包括:
程序的加載地址;
任務(wù)的優(yōu)先級(jí);
任務(wù)的當(dāng)前狀態(tài);
任務(wù)打開(kāi)的一些資源:網(wǎng)絡(luò)、文件設(shè)備等待;
。。。
需要注意的是:上面的 LDT、TSS,是 x86 處理器中設(shè)計(jì)的運(yùn)行機(jī)制,是處理器要求這樣的。
而 TCB 不是處理器要求的,它是操作系統(tǒng)的實(shí)現(xiàn)者自己來(lái)構(gòu)建的,因此可以根據(jù)自己的需要來(lái)進(jìn)行設(shè)計(jì)。
每一個(gè)應(yīng)用程序需要一個(gè) TCP 結(jié)構(gòu),所有的 TCB 結(jié)構(gòu)就可以構(gòu)成一個(gè)鏈表,便于操作系統(tǒng)來(lái)管理。
比如:在發(fā)生任務(wù)切換的時(shí)候,就可以順著鏈表頭,一次掃描鏈表上的每一個(gè) TCB 節(jié)點(diǎn)。
如果找到了當(dāng)前正在被執(zhí)行(即將被中止)的任務(wù),就把這個(gè)任務(wù)的狀態(tài)標(biāo)記為暫停,并移動(dòng)到鏈表的末尾,然后把鏈表頭部的第一個(gè)處于 ready 狀態(tài)的任務(wù),加載到處理器中去執(zhí)行。
當(dāng)然,Linux 系統(tǒng)中的處理過(guò)程更為復(fù)雜,它把每一個(gè)任務(wù)按照優(yōu)先級(jí)放在不同的等待隊(duì)列中,然后利用哈系桶算法來(lái)查找任務(wù)。
------ End ------
x86 處理器中的這三個(gè)概念,對(duì)于理解任務(wù)切換非常重要。
寫到這里,我總是覺(jué)得以上的文字描述還是有點(diǎn)朦朦朧朧,也許是自己還需要進(jìn)一步的理解其中的脈絡(luò)。
就先這樣吧,以后想到更好的描述方式了再與大家分享,謝謝!

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評(píng) >> 【評(píng)選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評(píng)選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開(kāi)始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 4 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 5 國(guó)產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來(lái)商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽(yáng)光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開(kāi)成長(zhǎng)空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營(yíng)收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?