摘 要:本文以虛擬機技術為主要研究對象,分析和研究了一些關鍵技術,如字節(jié)碼文件結(jié)構(gòu),虛擬機的內(nèi)存管理,虛擬機執(zhí)行引擎等,利用C/C++語言,設計虛擬機平臺的關鍵模塊。
關鍵詞:虛擬機 字節(jié)碼 內(nèi)存管理 執(zhí)行引擎
中圖分類號:TP302文獻標識碼:A文章編號:1674-098X(2011)02(c)-0106-01
1 概述
虛擬機(Virtual Machine)指通過軟件模擬的具有完整硬件系統(tǒng)功能的、運行在一個完全隔離環(huán)境中的完整計算機系統(tǒng)。虛擬機能夠模擬真實的計算機的實際運行過程,接受指令系統(tǒng)的指令,完成計算或者數(shù)據(jù)處理等任務。虛擬機應該具有精簡的指令集,高效的內(nèi)存管理機制,更適用于資源受限的平臺。
虛擬機實際上就是一個程序,生命周期劃分為五個階段,分別為建立出錯日志,處理命令行,構(gòu)造環(huán)境,字節(jié)碼驗證,執(zhí)行指令。
2 平臺的設計實現(xiàn)
2.1 建立出錯日志
虛擬機的基本操作是由main()函數(shù)控制的。
虛擬機以創(chuàng)建一個出錯日志文件開始了自己的生命歷程。每出現(xiàn)一個錯誤,就會在控制臺上顯示一條信息,同時還要把它記錄到某個出錯日志文件里去。與被記錄到出錯日志文件里去的出錯信息相比,被發(fā)送到控制臺去的出錯信息所提供的信息量相對要少一些。比較詳細的出錯情況都將記錄在出錯日志文件里,在控制臺上看到的出錯信息則比較簡潔。運行時系統(tǒng)出現(xiàn)的問題都將以易于理解的XML格式記錄下來,對顯示到控制臺上的信息則不進行排版。
2.2 處理命令行
在創(chuàng)建了出錯日志文件之后,虛擬機將對其命令行上的參數(shù)進行處理。
虛擬機是通過命令行上的命令來啟動和運行的。在命令行上給出的字節(jié)碼可執(zhí)行文件的文件名后綴必須是“.RUN”,并且這幾個字母必須全部大寫。在字節(jié)碼可執(zhí)行文件的前面,可以給出一個或者多個虛擬機命令行選項。命令行選項的作用是改變虛擬機的行為。命令行選項的第一個字符必須是一個短劃線字符(“-”)。為了區(qū)分字節(jié)碼可執(zhí)行文件和虛擬機的命令行選項,字節(jié)碼文件名的第一個字符將不允許是短劃線字符。短劃線字符、選項字母以及選項字母后的任何內(nèi)容之間不允許有空白間隔。在字節(jié)碼可執(zhí)行文件的后面,可以給出一些命令行參數(shù),這些參數(shù)將被傳遞給可執(zhí)行文件本身。
2.3 構(gòu)造環(huán)境
根據(jù)命令行上給出的參數(shù)建立一個可執(zhí)行環(huán)境并初始化。初始化虛擬機的寄存器,構(gòu)造一個人工地址空間,把字節(jié)碼可執(zhí)行文件讀入這個人工地址空間。
2.3.1 字節(jié)碼可執(zhí)行文件
字節(jié)碼可執(zhí)行文件里分為4個獨立的部分,有一個文件頭,一個符號表,一個字符串表和一個字節(jié)碼部分。虛擬機先打開字節(jié)碼可執(zhí)行文件,讀入它的文件頭和調(diào)試信息,檢查文件類型標志碼和字節(jié)碼長度。它的字節(jié)碼可執(zhí)行文件的標志碼必須是“0xDEED”,如果不是則表明該文件不是一個字節(jié)碼可執(zhí)行文件,虛擬機將退出此次執(zhí)行。如果字節(jié)碼區(qū)段的長度為0,虛擬機會認為沒有指令可供執(zhí)行,也將退出此次執(zhí)行。
2.3.2 地址空間
如果文件頭通過檢測,虛擬機就會根據(jù)頭文件信息加上命令行給出的選項來建立虛擬機的地址空間。虛擬機的地址空間由一個正文段、一個數(shù)據(jù)堆棧和一個堆棧段三個內(nèi)存段組成。正文段的長度就是這個可執(zhí)行文件的字節(jié)碼區(qū)段的長度。堆棧和數(shù)據(jù)堆的長度通過命令行設定或者取它們的缺省值。可執(zhí)行文件的字節(jié)碼區(qū)段的長度與數(shù)據(jù)堆和堆棧所要求的長度加起來得到一個數(shù)字,這個數(shù)字大于宿主主機上的可用物理內(nèi)存量,虛擬機將退出執(zhí)行。反之,虛擬機將向宿主操作系統(tǒng)申請分配一個無符號字節(jié)數(shù)組,它的長度就是剛才計算出來的和,并會把第一個字節(jié)的地址賦值給一指針變量。分配到地址空間后,用來劃分各個內(nèi)存段的寄存器將被初始化為相應的值。$IP和$FP寄存器將設置為0,$SP寄存器將設置為與$TOP寄存器里保存的同樣的值。最后把字節(jié)碼可執(zhí)行文件的字節(jié)碼區(qū)段加載到虛擬機地址空間中的正文段中。
2.4 字節(jié)碼驗證
虛擬機將檢查每一條字節(jié)碼指令中的各個元素是否合法有效。驗證器會檢查指令有一個合法的操作碼且對應于一條真實的指令,寄存器操作數(shù)引用的是一個實際存在的寄存器,地址在合法范圍內(nèi)。再檢查指令是完整的,指令的操作數(shù)是否合乎規(guī)定。虛擬機運行時系統(tǒng)將把字節(jié)碼可執(zhí)行文件中以降序格式存儲著的數(shù)值加載到內(nèi)存之后轉(zhuǎn)換為宿主機器格式。如果檢查到錯誤,在控制臺上將顯示一條簡短的消息,并把詳細情況記錄到出錯日志里。驗證過程從地址0開始,直到數(shù)據(jù)堆段的起始點為止。驗證器檢查完一條指令之后,它將預料內(nèi)存中的下一個字節(jié)或者是另外一條指令的操作碼或者是正文段的結(jié)束點。這種驗證方法不允許我們把數(shù)據(jù)存放在正文段里。換句話說,驗證器堆正文段的要求是它只能由字節(jié)碼指令構(gòu)成。指令可能不同,但是它們的彪馬格式是相同的。
2.5 執(zhí)行引擎
指令是被虛擬機匯編器轉(zhuǎn)換為字節(jié)碼的語句。一條指令是由一個操作碼和零個或多個操作數(shù)組成。執(zhí)行引擎是虛擬機的核心,指令集定義了它的行為。指令集以堆棧為中心,而不是以傳統(tǒng)的寄存器為中心。
虛擬機把把當前字節(jié)與虛擬機指令集中所有的指令操作碼進行比較。如果找到一個匹配,虛擬機將執(zhí)行該操作碼所代表的指令,反之,虛擬機會認為自己遇到一個致命錯誤,并將報告這個錯誤然后退出執(zhí)行。虛擬機從位于人工地址空間最底部的那條指令開始執(zhí)行,連續(xù)執(zhí)行字節(jié)碼指令,直到處理完結(jié)束指令或者遇到一個嚴重錯誤而停止。結(jié)束指令將使程序控制從執(zhí)行函數(shù)返回到主函數(shù)。
3 結(jié)語
虛擬機的執(zhí)行步驟如下:(1)以代參數(shù)的控制命令行方式啟動虛擬機;(2)提取信息,可執(zhí)行文件全路徑,數(shù)據(jù)堆和堆棧的大小,日志文件記錄的內(nèi)容,處理命令行;(3)創(chuàng)建日志文件,虛擬機運行過程中根據(jù)自動參數(shù)記錄指定的信息;(4)裝在可執(zhí)行文件中的內(nèi)容,讀入文件頭,符號表,字符串表,字節(jié)碼;(5)驗證可執(zhí)行文件頭數(shù)據(jù),檢查文件類型標志碼,格式是否正確,是否有非零長度的字節(jié)碼;(6)初始化運行環(huán)境,初始化虛擬機內(nèi)存模型,初始化各段寄存器內(nèi)容,將可執(zhí)行字節(jié)碼加載到正文段,將全局數(shù)據(jù)加載到數(shù)據(jù)段;(7)驗證可執(zhí)行文件中的字節(jié)碼,檢查每條指令是否完整,操作碼,寄存器,地址是否在合法范圍內(nèi),并把降序格式數(shù)值轉(zhuǎn)換為宿主機的編碼格式;(8)執(zhí)行字節(jié)碼,在指令指針的控制下依次執(zhí)行字節(jié)碼,直到結(jié)束指令;(9)虛擬機結(jié)束運行。
參考文獻
[1]Bill Blunden[著],楊濤,楊曉云,王建橋,等[譯].虛擬機的設計與實現(xiàn)-C/C++機械[M].工業(yè)出版社,2003.
[3]探矽工作室.深入嵌入式JAVA虛擬機[M].上海科學技術出版社,2004.
[4]劉黎明,王昭順.64位虛擬機SPANVM的設計與實現(xiàn)[J].計算機工程與科學,2007.
[5]柴樹杉,劉福江,陳創(chuàng).COMET虛擬機的設計與實現(xiàn)[J].計算機與信息技術,2008.