nachos操作系统初步认识
一、Nachos總體描述
1.1?Nachos虛擬機
Nachos模擬一個真實的CPU和硬件設備,包括中斷和內存管理。Java中的包nachos.machine提供了這個模擬器。
Nachos模擬器用nachos.conf文件安裝在不同的工程上。它詳細描述了模擬器中包含哪些硬件設備和Nachos內核如何使用硬件。工程的說明書包括適當的配置文件,如果必要的話,可以改動工程的宣傳冊文件需要完成這個工程。
Nachos的啟動進程類似于真實的虛擬機。nachos.machine.Machine.class的一個實例用來啟動Nachos。計算機硬件(虛擬機類)首先初始化設備包括中斷控制器,定時器,電梯控制器,MIPS進程,和文件系統。?
虛擬機類對象把控制權交給特定的自動分級AutoGrader裝置,相當于從硬盤上載入啟動引導程序的代碼。是AutoGrader產生了Nachos內核,并開始運行系統。學生們不必關心這一步啟動工作,真正有趣的部分從內核開始。?
Nachos的內核僅僅是nachos.machine.Kernal的一個子類。比如說,線程項目用的是nachos.threads.ThreadedKernel。
Nachos虛擬機包括很多硬件設備。有一些在現代計算機中普遍存在(如:網絡接口),但有些(比如說電梯控制)是Nachos特有的。Machine文件中的大多數類是硬件模擬的一部分,而在machine文件之外的類是Nachos操作系統的。
Nachos中斷管理是通過nachos.machine.Interrupt?類通過維持一個事件隊列來模擬。
1.2?jdb的使用
在跟蹤程序分析執行流程時僅僅使用System.out輸出信息只能進行一些簡單的驗證,很難完成龐大工程的調試分析,這時候我用到了jdb來進行調試。jdb的主要命令包括:
run?--?開始運行程序?
stop?in?包.類.函數名?--?設置在對應函數進入時觸發的斷點?
stop?at?包.類:行號?--?設置在指定文件特定行的斷點?print?變量名或者表達式?--?輸出變量或者經過運算的值?cont?--?在斷點處理后繼續執行?threads?--?顯示正在運行的線程?
suspend/resume?id?--?掛起/恢復一個線程?thread?tid?--?切換到特定線程
在進行多線程的調試時,要不斷對線程進行跟蹤,掛起原線程進入子線程,執行完畢后回到父線程,用jdb調試可以清晰的看到多線程的運行過程。
1.3?代碼分析過程
下面是我對nachos運行過程的詳細解讀:
分析nachos腳本,發現腳本中有?java?nachos.machine.Machine?找到machine.java?
開始從main函數分析源代碼?進入autoGrader.java?
分析出selfTest進行演示,進程創建?進入Kernel.java?
因為Kernel是一個抽象類,所以肯定有實現Kernel的實例?
nachos.conf配置文件中包含Kernel.kernel?=?nachos.threads.ThreadedKernel?在threadedKernel.java中,找到selfTest()?進入Kthread.java?
通過selfTest()找到PingTest?
在PingTest里就包含了完整的運行proj1的信息?
PingTest是繼承runnable接口的類,runnable是一個Java中的接口
解讀KThread.java代碼:?解析KThread中的方法:??
KThread():?
創建線程時如果是第一個線程,即當前線程未空,就調用ThreadedKernel.scheduler?也就是nachos.threads.RoundRobinScheduler的newThreadQueue方法,并創建一個先進先出隊列,并創建一個空閑線程,名為idle?如果當前線程非空,就創建線程控制塊tcb();??
setName();?設置名字??
getName();?取得名字??
toStirng();?重寫toString方法??
compareTo(Object?o);?線程之間通過線程id進行比較??
fork()?
導致線程開始執行,結果就是兩個線程正在執行,一個是當前線程,一個是被執行的線程。??
Finish()?
結束當前線程并加入調度銷毀線程,當一個線程的方法返回時自動執行該方法。如果當前的線程因為棧或者另一個之星狀態一直在被使用不能被立即銷毀,那么這個線程就會在其他線程運行時自動銷毀。??
Sleep()?
由于當前線程結束或者阻塞,而放棄CPU;如果當前的線程被阻塞,一些線程會把它喚醒,然后將它加入就緒等待隊列,這樣它可以被重新調度了。或者是該線程結束,那么就調度此線程在下一個線程運行時銷毀該線程。?調用sleep就可以讓CPU切換給其他線程執行??
ready()?
將當前線程加入就緒隊列,并將該線程的狀態改為ready狀態??
run()?
將這個線程放在CPU上執行,保存進程的當前狀態并調用新線程,載入新線程的狀態。新線程就成了當前線程,如果新線程與舊線程是相同的,這個方法必須被調用,之前運行的線程必須從運行狀態轉到阻塞或者就緒等待狀態(取決語之前運行的線程在sleep狀態還是yield狀態)
二、Nachos中線程的運行機制
2.1?線程與TCB
1)KThread構造函數創建線程時創建TCB,若當前無線程時,創建第一個線程直接使用main線程執行并將tcb指向currentTCB。??
????2)當線程調用fork()方法,即在增加一個線程時調用tcb.start()??
3)當線程調用run()方法,使CPU運行當前線程發生上下文切換時,調用
tcb.contextSwitch切換到新的線程?
4)恢復運行環境時調用銷毀被標記刪除狀態的tcb
2.2?線程調度
線程調度是通過隊列控制的,隊列決定線程切換順序。?線程調度主要在文件KThread.java中?
?1)在系統創建第一個線程時創建線程隊列readyQueue??
2)每次創建線程時將線程加入隊列?
3)當線程狀態為就緒時,在線程隊列中標記為可以進入,加入等待隊列waitQueue并等待調度?
4)發生線程切換時,即調用yield()方法或sleep()方法時,將從線程隊列中取下一個線程執行?
5)每一個線程都有一個優先級,由調度器對線程的優先級進行增減,決定線程隊列中線程的出隊順序。不同的調度器對于優先級控制的實現不同。?
?Schedule?分為RoundRobinSchedule,PriorityScheduler,LotteryScheduler。??RoundRobinSchedule為輪換調度調度器,使用FiFo隊列?;PriorityScheduler為帶權優先調度器,根據線程執行時間、啟動順序等計算優先級?;?LotteryScheduler為彩票隨機調度器,隨機決定出隊順序,但是優先級高的線程被調用的概率更大。
2.3?線程的創建
創建一個線程時先創建線程TCB,指定線程名setName(),綁定Runnable對象?即使用調用tcb.start(new?Runnable()?{??public?void?run()?{??????runThread();??}?});?
?內核創建第一個空閑線程時直接命名?main并設為當前線程。?
tcb?=?TCB.currentTCB();???name?=?"main";?
?fork()方法啟動新線程,具體過程是,保存cpu狀態intStatus?=?
Machine.interrupt().disable(),調用TCB的start方法創建java線程執行到線
程切換?tcb.start();再恢復?cpu狀態,同時引發新線程執行,若有多個線程則喚醒下一個線程。?對于創建的第一個線程直接使用main線程執行。
總結
以上是生活随笔為你收集整理的nachos操作系统初步认识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统试验-Nachos系统调用实现
- 下一篇: Didn‘t find class “a