操作系統(tǒng)基礎(chǔ)知識(shí)梳理(1)中斷與異常
??想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:??
在持續(xù)探索開源鴻蒙操作系統(tǒng)內(nèi)核的過程中有必要從LINUX,AOSP或其他小型操作系統(tǒng)中先深入分析汲取基礎(chǔ)知識(shí)經(jīng)驗(yàn),進(jìn)而對(duì)照分析學(xué)習(xí)進(jìn)而更深入學(xué)習(xí)理論和進(jìn)行實(shí)踐。
接下來從操作系統(tǒng)的基礎(chǔ)知識(shí)按照常規(guī)劃分結(jié)構(gòu),從硬件基礎(chǔ)結(jié)構(gòu),操作系統(tǒng)結(jié)構(gòu),內(nèi)存管理,進(jìn)程線程,操作系統(tǒng)調(diào)度,同步原語,文件系統(tǒng)與存儲(chǔ),設(shè)備管理,系統(tǒng)虛擬化,網(wǎng)絡(luò)協(xié)議,安全,調(diào)試,幾個(gè)部分來進(jìn)行基礎(chǔ)知識(shí)的梳理。深入了解操作系統(tǒng)的內(nèi)核,補(bǔ)全基礎(chǔ)知識(shí)。
操作系統(tǒng)運(yùn)行機(jī)制(中斷與異常)
中斷和異常基礎(chǔ)知識(shí)
操作系統(tǒng)中斷和異常是計(jì)算機(jī)系統(tǒng)中重要的概念,它們可以幫助操作系統(tǒng)處理各種事件和錯(cuò)誤
中斷(Interrupt)
中斷是指在計(jì)算機(jī)執(zhí)行程序時(shí),突然發(fā)生的一些事件,例如輸入輸出操作完成、定時(shí)器超時(shí)、硬件錯(cuò)誤等等。當(dāng)發(fā)生中斷時(shí),操作系統(tǒng)會(huì)停止當(dāng)前進(jìn)程的執(zhí)行,并處理中斷事件。處理完畢后,操作系統(tǒng)會(huì)回到原來的進(jìn)程并繼續(xù)執(zhí)行。
- 外部硬件設(shè)備產(chǎn)生的信號(hào)如鍵盤按鍵響應(yīng),鼠標(biāo)響應(yīng)
- 異步:產(chǎn)生原因和當(dāng)前的執(zhí)行指令無關(guān),如程序被磁盤的讀寫打斷
異常(Execption)
異常是指在程序執(zhí)行過程中出現(xiàn)的錯(cuò)誤或非正常情況。例如,除以零、訪問不存在的內(nèi)存地址等等。當(dāng)發(fā)生異常時(shí),操作系統(tǒng)會(huì)停止當(dāng)前進(jìn)程的執(zhí)行,并處理異常。處理完畢后,操作系統(tǒng)會(huì)終止當(dāng)前進(jìn)程并回收資源。
- 軟件的程序執(zhí)行而產(chǎn)生的事件
- 包括系統(tǒng)調(diào)用(System Call)-用戶程序請(qǐng)求操作系統(tǒng)提供服務(wù)
- 同步:產(chǎn)生和當(dāng)前執(zhí)行或試圖執(zhí)行的指令相關(guān)的
在不同的處理器架構(gòu)上定義有所不同實(shí)現(xiàn)方式也有所不同
主要在主流處理器架構(gòu)AArch64和x86-64上進(jìn)行探討。
- 在中斷處理方面,AArch64和x86-64的處理方式比較相似,都有中斷向量表和中斷處理程序。當(dāng)中斷發(fā)生時(shí),處理器會(huì)根據(jù)中斷向量表中的入口地址跳轉(zhuǎn)到對(duì)應(yīng)的中斷處理程序。不過,在中斷優(yōu)先級(jí)方面,AArch64使用的是基于中斷源編號(hào)的優(yōu)先級(jí),而x86-64使用的是基于中斷向量號(hào)的優(yōu)先級(jí)。
- 在異常處理方面,AArch64和x86-64的處理方式有一些區(qū)別。AArch64定義了3種不同的異常:同步異常、異步異常和中斷。同步異常是由當(dāng)前指令在執(zhí)行過程中發(fā)生的異常,而異步異常則是由硬件或軟件事件觸發(fā)的異常。中斷則是一種特殊的異常,它由外部設(shè)備觸發(fā),與異步異常的處理方式相似。在AArch64中,異常處理程序被稱為異常向量表,其中包含了不同類型異常的入口地址。而在x86-64中,異常被稱為中斷,異常處理程序被稱為中斷處理程序,它們的處理方式和中斷處理方式相同。
此外,AArch64和x86-64在異常處理的寄存器保存和恢復(fù)方面也有一些不同。在AArch64中,異常處理程序會(huì)保存通用寄存器、程序狀態(tài)寄存器以及特定的系統(tǒng)控制寄存器。而在x86-64中,中斷處理程序會(huì)保存通用寄存器、標(biāo)志寄存器、指令指針以及特定的中斷控制寄存器。
AArch64
中斷
- 重置 (RESET) -最高級(jí)別的異常,但是由芯片內(nèi)部電器信號(hào)觸發(fā),(嚴(yán)格劃分不屬于外部中斷)。
- 中斷(Interrupt) -CPU外部信號(hào)觸發(fā),打斷執(zhí)行 ,如計(jì)時(shí)器中斷,串口終端,空閑中斷。
異常
- 中止(Abort) - 失敗的指令獲取或數(shù)據(jù)訪問,訪問到不可讀地址。
- 異常產(chǎn)生指令
- SVC : 用戶程序 -》 操作系統(tǒng)
- HVC : 客戶系統(tǒng) -》 虛擬機(jī)管理器
- SMC :Normal -> Secure World
X86-64
中斷(設(shè)備產(chǎn)生,異步)
- 可屏蔽 - 設(shè)備產(chǎn)生的信號(hào),通過中斷控制器與處理器項(xiàng)鏈,能夠被暫時(shí)屏蔽。
- 不可屏蔽:一些關(guān)鍵硬件的崩潰錯(cuò)誤。
異常
三大類分類 :
- 錯(cuò)誤 (Fault)可恢復(fù)(缺頁異常),段錯(cuò)誤(不可恢復(fù))。
- 陷阱 (Trap)無需回復(fù)。
- 中止 (Abort)嚴(yán)重錯(cuò)誤,不可恢復(fù),需要進(jìn)行機(jī)器檢查。
中斷和異常的產(chǎn)生機(jī)制
中斷
如圖所示當(dāng)發(fā)生異常 (如除以零錯(cuò)誤) 時(shí),CPU 會(huì)向操作系統(tǒng)異常處理程序發(fā)出信號(hào),以便其接管并處理異常。操作系統(tǒng)異常處理程序隨后確定異常的原因,并決定是否可以恢復(fù)。如果可以恢復(fù),處理程序?qū)L試從異常中恢復(fù)。如果無法恢復(fù),系統(tǒng)將崩潰.
當(dāng)發(fā)生中斷 (如設(shè)備請(qǐng)求) 時(shí),CPU 會(huì)向中斷處理程序發(fā)出信號(hào),以便其接管并處理中斷。中斷處理程序隨后確定中斷的原因,并決定是系統(tǒng)調(diào)用還是設(shè)備中斷。如果是系統(tǒng)調(diào)用,處理程序?qū)?zhí)行請(qǐng)求的系統(tǒng)調(diào)用。如果是設(shè)備中斷,處理程序?qū)⑻幚碓O(shè)備中斷 (如通過讀取設(shè)備數(shù)據(jù))。
在ARM架構(gòu)內(nèi)核和X86架構(gòu)內(nèi)核當(dāng)中,有如下所示的SOC連接方式。
當(dāng)中連線最多的部分是GIC。
也就是(General interrupt controller)部分有多根總線連接到不同的設(shè)備上。
- 硬件層:最下層為硬件連接層,對(duì)應(yīng)的是具體的外設(shè)與SoC的物理連接,中斷信號(hào)是從外設(shè)到中斷控制器,由中斷控制器統(tǒng)一管理,再路由到處理器上;
- 硬件相關(guān)層:這個(gè)層包括兩部分代碼,一部分是架構(gòu)相關(guān)的,比如ARM64處理器處理中斷相關(guān),另一部分是中斷控制器的驅(qū)動(dòng)代碼。
- 通用層:這部分也可以認(rèn)為是框架層,是硬件無關(guān)層,這部分代碼在所有硬件平臺(tái)上是通用的。
- 用戶層:這部分也就是中斷的使用者了,主要是各類設(shè)備驅(qū)動(dòng),通過中斷相關(guān)接口來進(jìn)行申請(qǐng)和注冊(cè),最終在外設(shè)觸發(fā)中斷時(shí),進(jìn)行相應(yīng)的回調(diào)處理。
中斷控制器GIC需要考慮的問題
- 如何指定不同中斷的優(yōu)先級(jí)。
- 低優(yōu)先級(jí)的終端處理中,出現(xiàn)高優(yōu)先級(jí)的中斷如何響應(yīng)。
- 嵌套中斷。
- 誰來處理中斷。
- 和中斷控制器協(xié)同的軟件怎么編寫。
在aarch64架構(gòu)中,GIC支持不同的中斷優(yōu)先級(jí),這樣可以確保重要的中斷可以優(yōu)先處理。中斷優(yōu)先級(jí)由中斷號(hào)和中斷類型確定,每個(gè)中斷都有一個(gè)唯一的中斷號(hào),它是一個(gè)32位的整數(shù),同時(shí),每個(gè)中斷也有一個(gè)對(duì)應(yīng)的中斷類型,可以是中斷或異常。
中斷優(yōu)先級(jí)是通過GIC中的中斷控制器寄存器來實(shí)現(xiàn)的。GIC提供了四個(gè)中斷優(yōu)先級(jí)寄存器,分別為CPU Interface控制器寄存器的ICC_PMR、Distributor控制器寄存器的ICDIPR、ICDIPTR和ICDIPRn(其中n是從0開始的中斷號(hào))。這些寄存器用于設(shè)置中斷優(yōu)先級(jí)和掩碼。ICC_PMR是CPU Interface控制器的一個(gè)寄存器,它用于指定中斷的優(yōu)先級(jí)閾值。當(dāng)中斷的優(yōu)先級(jí)高于這個(gè)閾值時(shí),中斷將被立即處理,否則將被掛起。這個(gè)閾值可以是0到255之間的任何值。ICDIPR是Distributor控制器的一個(gè)寄存器,它用于設(shè)置每個(gè)中斷的優(yōu)先級(jí)。每個(gè)中斷都有一個(gè)對(duì)應(yīng)的ICDIPR寄存器,它是一個(gè)8位的寄存器,用于指定中斷的優(yōu)先級(jí)。值越大,優(yōu)先級(jí)越高。ICDIPTR是Distributor控制器的一個(gè)寄存器,它用于將中斷連接到處理器。每個(gè)中斷都有一個(gè)對(duì)應(yīng)的ICDIPTR寄存器,它是一個(gè)8位的寄存器,用于指定中斷連接到哪個(gè)處理器。ICDIPRn是Distributor控制器的一組寄存器,用于設(shè)置和查詢每個(gè)中斷的優(yōu)先級(jí)和掩碼。每個(gè)中斷都有一個(gè)對(duì)應(yīng)的ICDIPRn寄存器,它是一個(gè)32位的寄存器,其中包含了中斷的優(yōu)先級(jí)和掩碼信息。通過這些寄存器,我們可以靈活地配置中斷的優(yōu)先級(jí),從而確保系統(tǒng)能夠高效地處理各種中斷信號(hào)。
除了中斷控制器寄存器控制中斷號(hào)其次還對(duì)中斷進(jìn)行了劃分 ,VFIQ,VIRQ,IRQ ,F(xiàn)IQ,SError。IRQ是指普通中斷,優(yōu)先級(jí)低,處理緩慢,F(xiàn)IQ是快速中斷,常常為可信任的中斷源預(yù)留,SError是原因難以定位的異常,通常由異步中止Abort導(dǎo)致。,VIRQ和VFIQ是針對(duì)虛擬化的。
ARM GIC V2.0中給出的GIC模型如下:
在上圖中可以看到中斷路由功能的實(shí)現(xiàn)。
以及GIC主要包含三個(gè)重要部分。
Distributor、CPU interfaces 和 Virtual CPU interfaces。Virtual CPU interfaces 包含 Virtual interface control 和 Virtual CPU interface。
圖中Distributor部分的主要作用為檢測(cè)中斷源,控制中斷源行為和將中斷源分發(fā)到指定CPU的指定接口上。
具體功能包括:
- 全局啟用中斷轉(zhuǎn)發(fā)到 CPU 接口。
- 開啟或關(guān)閉每一個(gè)中斷。
- 為每個(gè)中斷設(shè)置優(yōu)先級(jí)。
- 為每個(gè)中斷設(shè)置目標(biāo)處理器列表。
- 設(shè)置每個(gè)外設(shè)中斷觸發(fā)方式(電平觸發(fā)、邊緣觸發(fā))。
- 為每個(gè)中斷設(shè)置組。
- 將 SGI 轉(zhuǎn)發(fā)到一個(gè)或多個(gè)處理器。
- 每個(gè)中斷狀態(tài)可見。
- 提供軟件設(shè)置或清除外設(shè)中斷的掛起狀態(tài)的一種機(jī)制。
在早期的中斷控制器中并不是這種架構(gòu),在我們常規(guī)使用的Contex M2-M3系列芯片中如今仍然使用的是內(nèi)嵌式中斷向量控制器NVIC,在NVIC中會(huì)維護(hù)一張表,中斷向量表是一個(gè)表,這個(gè)表里面存放的是中斷向量。中斷服務(wù)程序的入口地址或存放中斷服務(wù)程序的首地址成為中斷向量,因此中斷向量表是一系列中斷服務(wù)程序入口地址組成的表。這些中斷服務(wù)程序(函數(shù))在中斷向量表中的位置是由半導(dǎo)體廠商定好的,當(dāng)某個(gè)中斷被觸發(fā)以后就會(huì)自動(dòng)跳轉(zhuǎn)到中斷向量表中對(duì)應(yīng)的中斷服務(wù)程序(函數(shù))入口地址處。
中斷被劃分為三種類型:
SGI(Software Generated Interrupt) - 軟件觸發(fā)中斷:通常用于多核間通訊,最多支持 16 個(gè) SGI 中斷,硬件中斷號(hào)從 ID0~ID15。
PPI(Private Peripheral Interrupt) - 私有外設(shè)中斷:是每個(gè) CPU 私有的中斷。最多支持 16 個(gè) PPI 中斷,硬件中斷號(hào)從 ID16~ID31。可以處理指定核心的中斷任務(wù)
SPI(Shared Peripheral Interrupt)- 公用外設(shè)中斷:最多可以支持 988 個(gè)外設(shè)中斷,硬件中斷號(hào)從 ID32~ID1019,可以處理按鍵中斷,串口中斷等。
中斷源有很多,為了區(qū)分這些不同的中斷源肯定要給他們分配一個(gè)唯一 ID,這些 ID 就是中斷 ID。每一個(gè) CPU 最多支持 1020 個(gè)中斷 ID,中斷 ID 號(hào)為 ID0~ID1019。這 1020個(gè) ID 包含了 PPI、SPI 和 SGI,那么這三類中斷是如何分配這 1020 個(gè)中斷 ID 的呢?這 1020 個(gè) ID 分配如下:
ID0~ID15:這 16 個(gè) ID 分配給 SGI。
ID16~ID31:這 16 個(gè) ID 分配給 PPI。
ID32~ID1019:這 988 個(gè) ID 分配給 SPI,像 GPIO 中斷、串口中斷等這些外部中斷 ,至于具體到某個(gè) ID 對(duì)應(yīng)哪個(gè)中斷那就由半導(dǎo)體廠商根據(jù)實(shí)際情況去定義了。比如 I.MX6U的總共使用了 128 個(gè)中斷 ID,加上前面屬于 PPI 和 SGI 的 32 個(gè) ID, I.MX6U 的中斷源共有 128+32=160個(gè),這 128 個(gè)中斷 ID 對(duì)應(yīng)的中斷在《I.MX6ULL 參考手冊(cè)》的“3.2 Cortex A7 interrupts”小節(jié)NXP 官方 SDK中的文件 MCIMX6Y2C.h,在此文件中定義了一個(gè)枚舉類型 IRQn_Type,此枚舉類型就枚舉出了 I.MX6U 的所有中斷,代碼如下所示:
GIC中斷搶占
GIC中斷控制器支持中斷優(yōu)先級(jí)搶占,一個(gè)高優(yōu)先級(jí)中斷可以搶占一個(gè)低優(yōu)先級(jí)且處于active狀態(tài)的中斷,即GIC仲裁單元會(huì)記錄和比較當(dāng)前優(yōu)先級(jí)最高的pending狀態(tài),然后去搶占當(dāng)前中斷,并且發(fā)送這個(gè)最高優(yōu)先級(jí)的中斷請(qǐng)求給CPU,CPU應(yīng)答了高優(yōu)先級(jí)中斷,暫停低優(yōu)先級(jí)中斷服務(wù),進(jìn)而去處理高優(yōu)先級(jí)中斷。
GIC會(huì)將pending狀態(tài)優(yōu)先級(jí)最高的中斷請(qǐng)求發(fā)送給CPU。
在這里我們就必須要重新回顧剛才提到的圖片中的CPU interface部分的更詳細(xì)的信息。
??GIC?
? 為每個(gè) ??CPU?
? 接口上每個(gè)受支持的中斷維護(hù)一個(gè)狀態(tài)機(jī)。下圖顯示了此狀態(tài)機(jī)的實(shí)例,以及可能的狀態(tài)轉(zhuǎn)換。
在這個(gè)單元中包含了 Inactive ,Pending,Active and Pending以及Active四種狀態(tài),和操作系統(tǒng)進(jìn)程的狀態(tài)類似,我們重點(diǎn)關(guān)注轉(zhuǎn)換過程而不是狀態(tài)本身。
(1) 當(dāng)GIC檢測(cè)到一個(gè)中斷發(fā)生時(shí),會(huì)將該中斷標(biāo)記為pending狀態(tài)(A1)。
(2) 對(duì)處于pending狀態(tài)的中斷,仲裁單元回確定目標(biāo)CPU,將中斷請(qǐng)求發(fā)送到這個(gè)CPU上。
(3) 對(duì)于每個(gè)CPU,仲裁單元會(huì)從眾多pending狀態(tài)的中斷中選擇一個(gè)優(yōu)先級(jí)最高的中斷,發(fā)送到目標(biāo)CPU的CPU Interface模塊上。
(4) CPU Interface會(huì)決定這個(gè)中斷是否可以發(fā)送給CPU。如果該終端優(yōu)先級(jí)滿足要求,GIC會(huì)發(fā)生一個(gè)中斷信號(hào)給該CPU。
(5) 當(dāng)一個(gè)CPU進(jìn)入中斷異常后,會(huì)去讀取GICC_IAR寄存器來響應(yīng)該中斷(一般是Linux內(nèi)核的中斷處理程序來讀寄存器)。寄存器會(huì)返回硬件中斷號(hào)(hardware interrupt ID),對(duì)于SGI中斷來說是返回源CPU的ID。
總結(jié)整理為 添加新的掛起狀態(tài)(A1,A2),刪除掛起狀態(tài)(B1,B2),掛起到激活狀態(tài)(C),掛起到激活和掛起(D),刪除激活狀態(tài)。
從GIC角度看,GIC會(huì)發(fā)送高優(yōu)先級(jí)中斷請(qǐng)求給CPU。
但是目前CPU處于關(guān)中斷狀態(tài),需要等低優(yōu)先級(jí)中斷處理完畢,直到發(fā)送EOI給GIC。
然后CPU才會(huì)響應(yīng)pending狀態(tài)中優(yōu)先級(jí)最高的中斷進(jìn)行處理。
所以Linux下:
- 高優(yōu)先級(jí)中斷無法搶占正在執(zhí)行的低優(yōu)先級(jí)中斷。
- 同處于pending狀態(tài)的中斷,優(yōu)先響應(yīng)高優(yōu)先級(jí)中斷進(jìn)行處理。
對(duì)于ARM體系的處理器,通過判斷CPSR寄存器中的I位或F位的值確定處理器是否通過啟動(dòng)中斷確認(rèn)過程來響應(yīng)中斷信號(hào),處理搶占中斷是,處理器必須保存并稍后恢復(fù)為剛剛活動(dòng)的ISR的上下文,
優(yōu)先級(jí)下降意味著中斷的優(yōu)先級(jí)不再影響 CPU 接口上的運(yùn)行優(yōu)先級(jí),因此不會(huì)阻止中斷搶占。在 GICv1 實(shí)現(xiàn)中,僅當(dāng)中斷停用時(shí)才會(huì)發(fā)生優(yōu)先級(jí)下降,但在 GICv2 實(shí)現(xiàn)中,優(yōu)先級(jí)下降和中斷停用可以分開。這也就解決了剛剛提出的具有沖突可能的問題。
在虛擬機(jī)中如何支持IRQ和FIQ中斷
該用例來自于GICV2.0的說明文檔,指出,在CPU需要進(jìn)行虛擬化時(shí),GIC的響應(yīng)方式。
安全軟件分配:
對(duì)組 0 的安全中斷,作為 FIQ 信號(hào)發(fā)送到處理器。
對(duì)組 1 的非安全中斷,作為 IRQ 向處理器發(fā)出信號(hào)。
虛擬機(jī)管理程序:
使用 GIC 上的虛擬化擴(kuò)展的功能實(shí)現(xiàn)虛擬分發(fā)服務(wù)器。此虛擬分發(fā)服務(wù)器可以將來自 GIC 的 IRQ 中斷虛擬化為虛擬 IRQ 和虛擬 FIQ 中斷,并將其路由到相應(yīng)的虛擬機(jī)。
將物理 IRQ 路由到 Hyp 模式,以便虛擬分發(fā)服務(wù)器可以為其提供服務(wù)。當(dāng)虛擬化方案使用基于虛擬化擴(kuò)展(Virtualization Extensions,簡(jiǎn)稱VE)的虛擬化方式時(shí),物理中斷控制器(Physical GIC,簡(jiǎn)稱PGIC)會(huì)將物理IRQ路由到Hyp模式,Hypervisor進(jìn)行處理。硬件會(huì)根據(jù)中斷的優(yōu)先級(jí)和路由信息將中斷發(fā)送到正確的處理器模式中(如Hyp模式、Guest模式等)。
在虛擬機(jī)上運(yùn)行的客戶機(jī)操作系統(tǒng)將中斷分配給組 0 或組 1,以將其分配為 FIQ 或 IRQ。對(duì) GIC 分發(fā)服務(wù)器寄存器的訪問將捕獲到虛擬機(jī)管理程序,因此可以訪問虛擬分發(fā)服務(wù)器。
虛擬 CPU 接口將這些中斷作為虛擬 FIQ 或虛擬 IRQ 發(fā)出信號(hào)。此虛擬化受虛擬機(jī)管理程序控制,對(duì)來賓操作系統(tǒng)不可見。
當(dāng) GIC 向處理器發(fā)送 IRQ 信號(hào)時(shí),中斷將路由到 Hyp 模式。虛擬機(jī)管理程序確定中斷是針對(duì)自身還是針對(duì)來賓操作系統(tǒng)。如果是針對(duì)來賓操作系統(tǒng),它將確定:
哪個(gè)客戶機(jī)操作系統(tǒng)必須處理中斷。
該來賓操作系統(tǒng)是否已將中斷配置為 FIQ 或 IRQ。
中斷優(yōu)先級(jí),基于目標(biāo)來賓操作系統(tǒng)的優(yōu)先級(jí)配置。
綜合而言可以理解為虛擬機(jī)的中斷是通過虛擬中斷控制器(VGIC)轉(zhuǎn)發(fā)給物理中斷控制器(PGIC)來實(shí)現(xiàn)的。當(dāng)虛擬機(jī)需要處理中斷時(shí),VGIC會(huì)將中斷發(fā)送給PGIC,PGIC會(huì)根據(jù)中斷的優(yōu)先級(jí)和路由信息將中斷發(fā)送給相應(yīng)的虛擬機(jī)。
系統(tǒng)調(diào)用
系統(tǒng)調(diào)用是指運(yùn)行在用戶空間的程序向操作系統(tǒng)內(nèi)核請(qǐng)求需要更高權(quán)限運(yùn)行的服務(wù)。
系統(tǒng)提供用戶程序與操作系統(tǒng)之間的接口
- 用戶調(diào)用系統(tǒng)調(diào)用API,傳遞參數(shù)給應(yīng)用程序。
- 應(yīng)用程序進(jìn)入內(nèi)核空間,調(diào)用系統(tǒng)調(diào)用處理程序。
- 內(nèi)核進(jìn)行權(quán)限檢查和參數(shù)驗(yàn)證,準(zhǔn)備系統(tǒng)調(diào)用參數(shù)。
- 內(nèi)核執(zhí)行系統(tǒng)調(diào)用指令,將處理器從用戶模式切換到內(nèi)核模式,進(jìn)入內(nèi)核態(tài)。
- 處理器在內(nèi)核模式下,保存現(xiàn)場(chǎng),即保存用戶態(tài)的寄存器狀態(tài)等信息,以備將來返回用戶空間時(shí)使用。
- 處理器執(zhí)行系統(tǒng)調(diào)用處理程序,內(nèi)核根據(jù)系統(tǒng)調(diào)用類型進(jìn)行相應(yīng)的處理,可能會(huì)訪問設(shè)備或文件系統(tǒng)等。
- 處理完系統(tǒng)調(diào)用后,內(nèi)核恢復(fù)現(xiàn)場(chǎng),即恢復(fù)之前保存的寄存器狀態(tài)等信息。
- 處理器退出內(nèi)核模式,返回用戶模式,即返回應(yīng)用程序。
- 應(yīng)用程序得到系統(tǒng)調(diào)用結(jié)果,進(jìn)行后續(xù)處理。
例如我們運(yùn)行庫函數(shù) getchar() ,會(huì)在庫函數(shù)中找到其函數(shù)實(shí)體,并調(diào)用內(nèi)核API接口使用匯編指令 SVC #0.
那么以下是從硬件視角進(jìn)行分析的一張圖。
以下是Linux系統(tǒng)常見的系統(tǒng)調(diào)用:
當(dāng)發(fā)生系統(tǒng)調(diào)用時(shí)可以用ptrace()進(jìn)行追蹤系統(tǒng)調(diào)用的情況,strace追蹤系統(tǒng)調(diào)用,ltrace追蹤庫函數(shù)的調(diào)用。
系統(tǒng)調(diào)用由于用戶直接操作到了內(nèi)核,所以其中的寄存器傳參,以及具體的指針訪問們必須經(jīng)過嚴(yán)格的檢驗(yàn)。但是如果進(jìn)行完備的指針檢測(cè)十分耗時(shí),所以需要進(jìn)行非全面檢查。Linux非全面檢查的房房是,初步檢測(cè)用戶指針是否屬于對(duì)應(yīng)進(jìn)程 的用戶內(nèi)存區(qū)域最大可能邊界,通過了初步檢測(cè),用戶指針可能仍然非法。
文章相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往下載:
https://ost.51cto.com/resource/2616