Linux從頭學(xué)13:想徹底搞懂“系統(tǒng)調(diào)用”的底層原理?建議您別錯過這篇【調(diào)用門】
作 者:道哥,10 年嵌入式開發(fā)老兵,專注于:C/C 、嵌入式、Linux。目錄關(guān)注下方公眾號,回復(fù)【書籍】,獲取 Linux、嵌入式領(lǐng)域經(jīng)典書籍;回復(fù)【PDF】,獲取所有原創(chuàng)文章( PDF 格式)。
-
門描述符
-
調(diào)用門特權(quán)級檢查規(guī)則
-
調(diào)用門的使用過程
-
安裝調(diào)用門
-
把調(diào)用門告訴用戶程序
-
用戶程序通過調(diào)用門進入系統(tǒng)函數(shù)
-
棧在不同特權(quán)級下的切換
例如:應(yīng)用程序的 CPL 和 RPL 都為 3,而操作系統(tǒng)中的函數(shù)所在的段 DPL = 0,不能通過特權(quán)級的檢查。看過上一篇文章的小伙伴一定知道,如果把目標(biāo)代碼段的描述符中,TYPE.C標(biāo)志設(shè)置為1,也就意味著這是一個依從(或者叫一致性)代碼段,就允許低特權(quán)級的用戶程序調(diào)用了。
門描述符
所謂的門,就是一個通道。通過這個通道,可以進入另一個代碼段中進行執(zhí)行。
調(diào)用門:用于低特權(quán)級代碼轉(zhuǎn)移到高特權(quán)級代碼;門描述符與之前介紹的段描述符本質(zhì)是一樣的,都是用來描述一個代碼段的信息,只不過門描述符增加了一層間接性。任務(wù)門:用于不同任務(wù)之間的調(diào)度;
中斷門:用于異步執(zhí)行中斷處理程序;
陷阱門:也用于執(zhí)行中斷處理程序,不過這里的中斷是處理器內(nèi)部產(chǎn)生的;
- 所謂的任務(wù)門可以簡單理解為用于任務(wù)切換。
- 因為一個 TSS 段中,保存的就是一個任務(wù)的上下文信息快照。
- 只要處理器發(fā)現(xiàn)選擇子指向的描述符是一個任務(wù)門(通過 TYPE 字段),它就執(zhí)行任務(wù)切換:
a. 保存當(dāng)前 CPU 中的上下文到當(dāng)前任務(wù)的 TSS 段中;b. 再把 TSS 選擇子中所指向的那個 TSS 段中的上下文內(nèi)容,加載到 CPU 寄存器中,這樣就實現(xiàn)了任務(wù)切換。
調(diào)用門特權(quán)級檢查規(guī)則
從調(diào)用門的名字就可以看出,它是為系統(tǒng)調(diào)用服務(wù)的。
參數(shù)個數(shù):調(diào)用者傳遞多少個參數(shù)給目標(biāo)代碼(是通過??臻g來傳參的);從以上這些字段來看,這簡直就是為:從低特權(quán)級的用戶代碼,調(diào)用高特權(quán)級的操作系統(tǒng)代碼,量身定做的,只要處理器在特權(quán)級上放過用戶程序一馬就可以了。DPL:表示這個調(diào)用門本身的特權(quán)級;
目標(biāo)代碼段選擇子:最終調(diào)用的目標(biāo)代碼段的選擇子,需要用這個選擇子到 GDT 中尋找目標(biāo)代碼段的基地址;
偏移量:調(diào)用的代碼距離目標(biāo)代碼段開始地址的偏移字節(jié)數(shù);
從以上規(guī)則可以再次看出:即使通過調(diào)用門,目標(biāo)代碼段只允許相同或者更低的特權(quán)級代碼進入,也驗證了之前所說的:高特權(quán)級代碼不會主動轉(zhuǎn)移到低特權(quán)級的代碼中。
- 當(dāng)前特權(quán)級 CPL (用戶程序)和請求特權(quán)級 RPL,必須 [高于或等于] 調(diào)用門中的 DPL;
即在數(shù)值上:CPL <= DPL,RPL <= DPL。(注意:這是調(diào)用門描述符里的 DPL)
- 當(dāng)前特權(quán)級 CPL(用戶程序),必須 [低于或等于] 目標(biāo)代碼段中的 DPL;
即在數(shù)值上:CPL >= 目標(biāo)代碼段描述符中的 DPL。
TYPE.C = 1:CPL 保持不變,仍然為用戶程序中的特權(quán)級 3;TYPE.C = 0: CPL 改變,變成目標(biāo)代碼段的特權(quán)級;
調(diào)用門的使用過程
安裝調(diào)用門
所謂的安裝,就是在GDT中構(gòu)造一個調(diào)用門描述符,讓它的目標(biāo)代碼段選擇子指向真正的代碼段。
把調(diào)用門的選擇子告訴用戶程序
按照之前的慣例,操作系統(tǒng)可以在用戶程序的頭部header中的約定位置處,填寫調(diào)用們的選擇子以及函數(shù)偏移地址:
RPL = 3;到 GDT 中去查找;
索引號 index = 8;
用戶程序通過調(diào)用門進入系統(tǒng)函數(shù)
當(dāng)用戶程序請求調(diào)用系統(tǒng)函數(shù)時,處理器就開始對這3 方的特權(quán)級展開檢查:
以上這些特權(quán)級的數(shù)值滿足調(diào)用門的特權(quán)級規(guī)則要求,于是就進入系統(tǒng)函數(shù)所在的代碼中執(zhí)行了。
- 用戶程序的 CPL = 3, RPL = 3;
- 調(diào)用門自身的 DPL = 3;
- 調(diào)用門中的目標(biāo)代碼段選擇子所指向的描述符(index = 7)中 DPL = 0;
棧的切換
x86處理器要求:當(dāng)前特權(quán)級 CPL 必須與目標(biāo)棧段的 DPL 相同。
------ End ------