日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

XV6系统调用实现

發(fā)布時(shí)間:2023/12/9 windows 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 XV6系统调用实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

X86的保護(hù)機(jī)制

x86 有四個(gè)特權(quán)級(jí),從 0(特權(quán)最高)編號(hào)到 3(特權(quán)最低)。在實(shí)際使用中,大多數(shù)的操作系統(tǒng)都使用兩個(gè)特權(quán)級(jí),0 和 3,他們被稱為內(nèi)核模式和用戶模式。當(dāng)前執(zhí)行指令的特權(quán)級(jí)存在于 %cs 寄存器中的 CPL 域中。

在 x86 中,中斷處理程序的入口在中斷描述符表(IDT)中被定義。這個(gè)表有256個(gè)表項(xiàng),每一個(gè)都提供了相應(yīng)的 %cs 和 %eip。

int指令的硬件動(dòng)作

一個(gè)程序要在 x86 上進(jìn)行一個(gè)系統(tǒng)調(diào)用,它需要調(diào)用 int n 指令,這里 n 就是 IDT 的索引。int 指令進(jìn)行下面一些步驟(硬件自動(dòng)完成):

  • 從 IDT 中獲得第 n 個(gè)描述符,n 就是 int 的參數(shù)。
  • 檢查 %cs 的域 CPL <= DPL,DPL 是描述符中記錄的特權(quán)級(jí)。
  • 如果DPL < CPL,就在 CPU 內(nèi)部的寄存器中保存 %esp 和 %ss 的值(即不會(huì)發(fā)生特權(quán)級(jí)切換,所以不用將程序低特權(quán)級(jí)別下的%esp 和 %ss保存到高特權(quán)級(jí)棧中)。
  • 從一個(gè)任務(wù)段(TSS)描述符中加載 %ss 和 %esp(高特權(quán)級(jí)棧對(duì)應(yīng)的%ss 和 %esp)。
  • 將 %ss 壓棧(低特權(quán)級(jí)的%ss壓入高特權(quán)級(jí)棧 )。
  • 將 %esp 壓棧(低特權(quán)級(jí)的%esp壓入高特權(quán)級(jí)棧)。
  • 將 %eflags 壓棧。
  • 將 %cs 壓棧。
  • 將 %eip 壓棧。
  • 清除 %eflags 的一些位。
  • 設(shè)置 %cs 和 %eip 為描述符中的值。

int 指令是一個(gè)非常復(fù)雜的指令,可能有人會(huì)問(wèn)是不是所有的這些操作都是必要的。檢查 CPL <= DPL 使得內(nèi)核可以禁止一些特權(quán)級(jí)系統(tǒng)調(diào)用。例如,如果用戶成功執(zhí)行了 int 指令,那么 DPL 必須是 3。如果用戶程序沒(méi)有合適的特權(quán)級(jí),那么 int 指令就會(huì)觸發(fā) int 13,這是一個(gè)通用保護(hù)錯(cuò)誤。再舉一個(gè)例子,int 指令不能使用用戶棧來(lái)保存值,因?yàn)橛脩艨赡苓€沒(méi)有建立一個(gè)合適的棧,因此硬件會(huì)使用任務(wù)段(TSS)中指定的棧(這個(gè)棧在內(nèi)核模式中建立)。

當(dāng)內(nèi)陷發(fā)生時(shí),處理器會(huì)做下面一些事。如果處理器在用戶模式下運(yùn)行,它會(huì)從TSS中加載 %esp 和 %ss,把老的 %ss 和 %esp 壓入新的棧中。如果處理器在內(nèi)核模式下運(yùn)行,上面的事件就不會(huì)發(fā)生。處理器接下來(lái)會(huì)把 %eflags,%cs,%eip 壓棧。對(duì)于某些內(nèi)陷來(lái)說(shuō),處理器會(huì)壓入一個(gè)錯(cuò)誤字。而后,處理器從相應(yīng) IDT 表項(xiàng)中加載新的 %eip 和 %cs。

圖 3-1 展示了一個(gè) int 指令之后的棧的情況,注意這是發(fā)生了特權(quán)級(jí)轉(zhuǎn)換(即描述符中的特權(quán)級(jí)DPL比 CPL中的特權(quán)級(jí)低的時(shí)候)棧的情況。如果這條指令沒(méi)有導(dǎo)致特權(quán)級(jí)轉(zhuǎn)換,x86 就不會(huì)保存 %ss 和 %esp。在任何一種情況下,%eip 都指向中斷描述符表中指定的地址,這個(gè)地址的第一條指令就是將要執(zhí)行的下一條指令,也是 int n 的中斷處理程序的第一條指令。操作系統(tǒng)應(yīng)該實(shí)現(xiàn)這些中斷處理程序。

操作系統(tǒng)可以使用 iret 指令來(lái)從一個(gè) int 指令中返回。它從棧中彈出 int 指令保存的值,然后通過(guò)恢復(fù)保存的 %eip 的值來(lái)繼續(xù)用戶程序的執(zhí)行。

特權(quán)級(jí)切換與棧切換

當(dāng)特權(quán)級(jí)從用戶模式向內(nèi)核模式轉(zhuǎn)換時(shí),內(nèi)核不能使用用戶的棧,因?yàn)樗赡懿皇怯行У摹S脩暨M(jìn)程可能是惡意的或者包含了一些錯(cuò)誤,使得用戶的 %esp 指向一個(gè)不是用戶內(nèi)存的地方。棧切換的方法是讓硬件從一個(gè)TSS中讀出新的%ss和新的 %esp 的值(內(nèi)核態(tài)棧的%ss個(gè)%esp,函數(shù) switchuvm會(huì)把用戶進(jìn)程的內(nèi)核棧頂?shù)刂反嫒隩SS中)。

XV6系統(tǒng)調(diào)用之特權(quán)級(jí)切換與棧切換

xv6 使用一個(gè) perl 腳本來(lái)產(chǎn)生IDT表項(xiàng)指向的中斷處理函數(shù)入口點(diǎn)。每一個(gè)入口都會(huì)壓入一個(gè)錯(cuò)誤碼(如果 CPU 沒(méi)有壓入的話),壓入中斷號(hào),然后跳轉(zhuǎn)到 alltraps。

Alltraps繼續(xù)保存處理器的寄存器:它壓入 %ds, %es, %fs, %gs, 以及通用寄存器EAX/EBX/ECX/EDX/ESP/EBP/ESI/EDI。這么做使得內(nèi)核棧上壓入一個(gè) trapframe(中斷幀)結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體包含了中斷發(fā)生時(shí)處理器的寄存器狀態(tài)(參見(jiàn)圖3-2)。處理器負(fù)責(zé)壓入 %ss,%esp,%eflags,%cs 和 %eip。處理器或者中斷入口會(huì)壓入一個(gè)錯(cuò)誤碼(如果某些中斷,處理器不壓入錯(cuò)誤碼,那么軟件中斷入口會(huì)壓入一個(gè)錯(cuò)誤碼,實(shí)際上目的就是為了保持所有中斷的trapframe一致),而alltraps負(fù)責(zé)壓入剩余的。中斷幀包含了所有處理器從當(dāng)前進(jìn)程的內(nèi)核態(tài)恢復(fù)到用戶態(tài)需要的信息,所以處理器可以恰如中斷開(kāi)始時(shí)那樣繼續(xù)執(zhí)行。特別的,userinit通過(guò)手動(dòng)建立中斷幀來(lái)達(dá)到這個(gè)目標(biāo)。

?Firgure 3-2的布局剛好和struct trapframe定義對(duì)應(yīng)起來(lái)。

被保存的 %eip 是 int 指令下一條指令的地址。%cs 是用戶代碼段選擇符。%eflags 是執(zhí)行 int 指令時(shí)的 eflags 寄存器,alltraps 同時(shí)也保存 %eax,它存有系統(tǒng)調(diào)用號(hào),內(nèi)核在之后會(huì)使用到它。

現(xiàn)在用戶態(tài)的寄存器都保存了,alltraps 可以完成對(duì)處理器的設(shè)置并開(kāi)始執(zhí)行內(nèi)核的 C 代碼。處理器在進(jìn)入中斷處理程序之前設(shè)置選擇符 %cs 和 %ss(硬件自動(dòng)完成);alltraps 設(shè)置 %ds 和 %es。

一旦段設(shè)置好了,alltraps 就可以調(diào)用 C 中斷處理程序 trap 了。它壓入 %esp 作為 trap 的參數(shù),%esp 指向剛在棧上建立好的中斷幀。然后它調(diào)用 trap。trap 返回后,alltraps 彈出棧上的參數(shù)然后執(zhí)行標(biāo)號(hào)為 trapret 處的代碼。我們?cè)诘诙玛U述第一個(gè)用戶進(jìn)程的時(shí)候跟蹤分析了這段代碼,在那里第一個(gè)用戶進(jìn)程通過(guò)執(zhí)行 trapret 處的代碼來(lái)退出到用戶空間。同樣地事情在這里也發(fā)生:彈出中斷幀會(huì)恢復(fù)用戶模式下的寄存器,然后執(zhí)行 iret 會(huì)跳回到用戶空間。

現(xiàn)在我們討論的是發(fā)生在用戶模式下的中斷,但是中斷也可能發(fā)生在內(nèi)核模式下。在那種情況下硬件不需要進(jìn)行棧轉(zhuǎn)換,也不需要保存棧指針或棧的段選擇符;除此之外的別的步驟都和發(fā)生在用戶模式下的中斷一樣,執(zhí)行的 xv6 中斷處理程序的代碼也是一樣的。而 iret 會(huì)恢復(fù)了一個(gè)內(nèi)核模式下的 %cs,處理器也會(huì)繼續(xù)在內(nèi)核模式下執(zhí)行。

總結(jié)

以上是生活随笔為你收集整理的XV6系统调用实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。