原帖地址:http://www.linuxdiyf.com/blog/?291/action_viewspace_itemid_405.html
實現Linux應用二進制兼容的意義
隨著操作系統技術的發展從注重性能到注重服務,操作系統所配套的服務軟件多少以及開發環境是否易用就成為決定一個操作系統生命力的關鍵因素。微軟今日壟斷地位的形成,就得益于微軟完整的應用軟件體系。而以前國產操作系統未能形成良性發展的局面,也是受阻于沒有完整的軟件體系的配套。所以,注重配套服務軟件開發,提高系統適用面就成為Kylin操作系統在設計和開發只初就統籌考慮的問題。
通過自己的力量,從頭為Kylin操作系統開發來所有應用軟件時間不允許,人力、物力上不可行。它山之石可以攻玉,我們必須借助目前現有成熟的應用軟件體系才能在較短時間內構成較完整的應用軟件體系,滿足用戶的基本需求。目前的應用軟件體系主要有Windows體系、UNIX體系和Linux體系等。Windows應用軟件體系具有應用數量、種類豐富,使用界面友好等特點,但存在操作系統大量技術細節不公開,難以支持的問題。UNIX體系同樣應用數量巨大,但存在版本眾多,并且各UNIX版本間不完全兼容的問題,大大限制了各UNIX版本間應用的移植,并且UNIX應用大多數無法免費獲得,也極大的限制了UNIX應用的普及。Linux應用軟件體系目前已形成一個從操作系統到數據庫管理系統,從中間件軟件到豐富的應用軟件的完整的軟件體系,正成為標準的軟件基礎設施。由于依托開源軟件體系,所以Linux操作系統的技術細節全部公開,并且遵循LSB應用接口。同時,許多Linux應用體系的軟件也采用了開源或免費方式,從而也極大地推動了Linux操作系統的成功。Kylin操作系統采用了兼容Linux二進制應用的技術路線,支持同平臺的Linux二進制應用不加任何修改地運行在Kylin操作系統上。通過兼容Linux應用體系,Kylin操作系統可以站在巨人的肩膀上,極大地改善市場生存環境,快速構成完整的Kylin體系,從而加快Kylin操作系統的應用推廣。
應用二進制兼容的主流實現技術
應用二進制兼容技術根據兼容實現層次可以分為硬件層兼容、操作系統層兼容、系統庫層兼容三種實現方式。
硬件層兼容技術以虛擬機技術為代表,如VMWare和Virtual PC等。虛擬機技術通常構建在操作系統(一般稱為HOS)之上,通過仿真硬件虛擬出完整的硬件系統。并在虛擬的硬件系統上安裝要兼容的操作系統(一般稱為GOS),并運行相應的應用程序。虛擬機環境中的被兼容操作系統由于運行在用戶態,無法直接操縱物理硬件,而必須通過虛擬機監視器(VMM)來中轉對硬件的特權操作,如頁表訪問、I/O訪問等。通過虛擬機技術的應用兼容方式對應用透明性好,兼容性好,但存在實現難度較大,性能低下等缺陷:據評測,應用虛擬一般降低約30%,尤其是IO性能,損失更大。
操作系統層兼容通過在操作系統內核中支持新的兼容操作系統系統調用來實現不同應用體系間的兼容。運行兼容應用時,操作系統將調用兼容操作系統的系統調用入口函數,完成對兼容應用的支持。采用操作系統層兼容技術同樣對兼容應用透明,兼容應用運行性能高。但存在兼容面窄的局限性,如UNIX與Linux體系間的兼容較容易實現,但UNIX、Linux與Windows體系間的兼容較困難。目前IBM的K42操作系統、GNU/BSD操作系統以及SUN的JANUS計劃均采用該技術方案實現了UNIX體系對Linux體系的兼容。
通過構造專門的動態連接庫,在用戶庫一級實現對兼容應用的支持是目前Wine等系統所采用的兼容技術途徑。用戶庫級的兼容技術途徑具有簡單和快捷的特點,但仿真層在動態鏈接庫中實現,不適用于靜態鏈接好的程序。
Kylin操作系統中Linux應用二進制兼容的設計
通過分析和比較 基于硬件仿真實現兼容的虛擬機技術、基于系統調用仿真實現的內核層兼容技術、以及修改系統共享庫實現的核外兼容技術等多種兼容技術,并同時考慮到效率和兼容效果、以及Kylin操作系統的內在特點,我們確定了以系統調用仿真實現的內核層兼容技術作為基礎實現Linux的應用兼容。
由于Linux操作系統的發行版本眾多,Linux系統的標準化是目前Linux世界的大勢所趨,其中由自由軟件組織發起的旨在規范Linux標準的LSB計劃獲得了眾多Linux廠商的響應和支持,紅帽、曼德拉等許多廠商均獲得了LSB的認證。用LSB規范作為Kylin對Linux應用兼容的標尺,使得Kylin作為Linux應用平臺同國際標準接軌成為我們的追求目標。
操作系統二進制兼容的總體結構
Kylin操作系統通過在內核中支持符合LSB標準的Linux系統調用實現了對Linux應用的兼容,并同時提供了對Linux應用加載、proc文件系統等的支持模塊。Linux應用兼容模塊的具體結構如下圖所示:
二進制兼容的實現
在確定上述技術路線后,通過解決下述的幾個關鍵技術點,我們在Kylin操作系統內核中的系統服務層實現了Linux二進制兼容服務。
Kylin對Linux應用二進制兼容的總體結構
Kylin操作系統的Linux應用加載模塊
操作系統為不同格式的文件創建初始執行環境時完成的工作大部分是相同的;主要區別在于需要根據文件的類型或格式為其建立用戶空間和用戶態堆棧。Kylin操作系統提供了對多種文件格式的加載器,完成對不同種類文件的識別和加載過程(這里的加載主要指對用戶空間的建立,不包括對用戶態堆棧的創建)。Kylin將系統中所有的加載器組織在一起成為一個加載器隊列。對于所有的文件,在其開頭的128個字節里都包含了關于該文件屬性的必要且充分的信息。因此,內核首先讀入執行文件的頭128字節,然后讓加載器隊列中的加載器輪流分析該文件頭,認領可執行文件。如果某個加載器辨認到了它代理的可執行文件,加載該文件的任務就交給它;否則內核就讓隊列中的下一個加載器繼續進行嘗試。對于不同操作系統的ELF文件,其加載過程是相同的。因此,Kylin只實現一個ELF文件加載器,其完成對所有ELF文件的識別和加載工作。當然,該加載器在識別出ELF文件后,仍需進一步對該文件來自的操作系統進行識別,至此才算完成對文件格式的確立工作。相同格式但來自不同操作系統的應用程序,對用戶態堆棧的初始布局也可能存在不同的要求。對于這樣的異地應用程序,需要對Kylin為本地文件創建的用戶態堆棧進行修改,以滿足其執行要求。Kylin使用堆棧修補過程來完成這項工作。雖然系統為所有ELF文件建立用戶空間所做的工作都相同,但動態連接的Kylin ELF文件和Linux ELF文件,對用戶態堆棧的初始布局卻存在不同的要求。為此,Kylin為Linux ELF文件設計了堆棧修補過程。
Kylin操作系統的Linux系統調用仿真模塊
系統調用集合定義了內核向用戶進程提供的服務接口,用戶應用可通過該接口使用操作系統提供的有關設備管理、輸入/輸出系統、文件系統、進程控制、通信以及存儲管理等方面的功能,而無需了解操作系統的內部結構和有關的硬件細節,從而減輕用戶負擔、保護系統、提高資源利用率。在大多數操作系統上,應用程序發出系統調用,到系統調用返回的整個過程主要包括下面幾個步驟:
·應用程序通過API請求服務;
·庫函數中的封裝例程通過某種與硬件平臺相關的自陷指令發出系統調用;
·自陷指令將執行模式變為內核態,執行系統調用處理程序,其取得系統調用的參數并調用對應的系統調用服務例程,在系統調用服務例程執行完畢后,對由系統調用服務例程得到的返回值進行必要的處理,然后返回用戶態;
·庫函數中的封裝例程將由操作系統內核得到的返回值交給應用程序。
Linux應用程序在Kylin上運行時,被連接到原始的Linux共享庫。因此,Kylin對Linux系統調用進行仿真,首先需要對本地的系統調用處理程序進行必要的修改,使其處理來自異地的系統調用請求時,能夠:
·取得由Linux系統調用封裝例程提供的參數;
·按Linux的約定將系統調用返回值傳遞給用戶態的異地系統調用封裝例程;
·使用Linux系統調用接口表中的系統調用服務例程完成來自Linux應用程序的服務請求;
Kylin有一個系統調用接口表,其中每個表項對應一個系統調用服務例程。表項由兩部分組成:系統調用參數的個數和指向系統調用服務例程的函數指針。系統調用接口表中表項的排列順序與系統調用號的順序對應。因此,可以將系統調用號轉換為對系統調用接口表的索引,并執行對應表項中函數指針所指向的系統調用服務例程,完成應用程序請求的服務。由于Kylin的系統調用與Linux的系統調用,從名稱、系統調用號、參數接口形式到具體的功能,都存在一定的差異,因此,對Linux應用程序中發出的系統調用請求,不能將其連接到Kylin本地的系統調用接口表,或直接使用本地的系統調用服務例程為其服務,而是需要設計一個Linux系統調用接口表,并對其中的系統調用在Kylin上進行模擬實現。
我們分兩步實現對Linux系統調用的仿真。首先,實現Linux系統調用接口表;然后,在Kylin上對接口表Linux系統調用接口表中的系統調用服務例程進行仿真。
從與硬件平臺是否相關的角度對Linux的系統調用進行劃分,可將其分成硬件平臺相關的系統調用和硬件平臺無關的系統調用兩類。對于與硬件平臺無關的系統調用,只需在Kylin上仿真一次;對于與硬件平臺相關的系統調用,則需要針對不同的硬件平臺(I386或IA64),分別在Kylin上進行仿真。對于所有的Linux系統調用,包括硬件相關和無關的、或者完成不同功能的,在Kylin上對其進行仿真的思路和方法都相同。首先,分析Linux系統調用的參數形式、返回值、實現的功能等情況;然后考察Kylin對該系統調用的支持情況;在完成上述準備工作后,就可以開始實現對該系統調用服務例程的仿真。對異地系統調用服務例程的仿真有三種情況:
第一,直接使用本地的系統調用服務例程完成所需的功能。
某些Linux系統調用,在Kylin上正好存在與之完全對應的系統調用,即兩者在參數個數、參數類型、完成的功能、返回值等方面都完全吻合。對于這些系統調用,可以直接使用本地的系統調用服務例程完成其所需的功能。通過向Linux系統調用接口表中這些系統調用對應的表項直接寫入指向本地系統調用服務例程的函數指針,可以實現這個目標。
第二,通過某種形式的轉換后,調用本地系統調用服務例程完成所需的功能
存在一些Linux系統調用,在Kylin上有與之功能相同或相似的系統調用,但雙方在使用的數據結構、標志的定義等方面還存在一定差異。Kylin為這些系統調用設計了一個封裝函數,封裝函數通過調用本地的系統調用服務例程完成Linux系統調用的主體工作,但在調用本地函數的前后,封裝函數對Linux和Kylin之間存在的各種差異進行轉換。在Linux系統調用接口表中這些系統調用對應的表項里,寫入指向對應的封裝函數的函數指針。另外,對于所有不是由本地系統調用服務例程直接實現的Linux系統調用服務例程,Kylin在其名字前加上前綴linux_,以和本地系統調用服務例程相區別;對于這些系統調用的參數所使用的數據類型或數據結構,如果與本地對應的數據類型或結構不相同,或者在本地根本不存在對應物,則按照Linux的約定,在本地重新對其進行定義,在其名字前也加上前綴linux_。
第三,對異地系統調用服務例程在本地進行重新實現。
存在一些Linux系統調用,在Kylin上不存在功能與之相似的系統調用。對于這些系統調用,只能在Kylin上對其進行重新實現。
Kylin操作系統的Linux proc文件系統仿真模塊
Proc文件系統是Linux系統內核對外接口之一,它是一個存在于內存中的偽文件系統, Linux應用程序通過該文件系統獲得內核信息或修改內核參數。目前,Kylin操作系統中實現了Linux proc文件系統仿真框架,它主要提供系統進程信息、系統設備信息等必要的內核信息,供Linux應用程序使用。
Kylin中的proc文件系統框架的由信息采集和信息輸出兩個子系統構成。其中信息采集子系統負責收集內核信息;信息輸出子系統部分負責提供對外接口,根據需要調用信息采集例程,并將內核信息封裝成Linux-proc的格式向外輸出。
由于proc文件系統需要的內核信息覆蓋虛存管理系統、文件系統、網絡協議、設備驅動等各個方面,因此信息采集子系統由分布在基本內核層和系統服務層各個子系統中的若干信息收集例程構成。
信息輸出子系統作為系統服務層中的一個服務模塊,以文件系統的形式向外提供信息。Kylin操作系統中實現了一個偽文件系統框架,該文件系統框架支持偽文件系統的創建、維護等操作。在該文件系統框架基礎上,出于安全性的考慮,我們實現了一個Linux的proc文件系統的子集,提供有限內核信息的讀操作接口。
Kylin操作系統的LSB標準化
為了實現Linux應用兼容的標準化,我們研究了LSB規范,LSB中對操作系統平臺作了詳細的規范,最基礎要求包括:系統調用兼容性;系統庫兼容性;系統工具兼容性;文件層次結構兼容性。LSB通過提供測試集來實現對標準的實施。目前lsb1.3標準中使用LSB-VSX、LSB-FHS、LSB-OS、LSB-USRGROUPS四個主要的測試族; 用于對上面幾個標準進行符合性測試。
由于在實現過程中,我們使用LTP提供的系統調用測試集作為Linux二進制系統調用的測試試程序,對系統調用兼容進行了全面而細致的調測試,確保了操作系統調用的兼容性。
由于Kylin操作系統內核層實現了Linux系統調用兼容,內核中對應用加載方式和應用符號解析進行了標準化支持,確保了函數庫的接口可以在運行時與應用連接,支持Linux標準的ELF格式,并按LSB標準提供了動態連接機制;因此Linux的系統庫無需修改就可以直接調用到Linux的系統調用。目前Kylin系統中配置了支持LSB標準的c庫、數學庫等常用系統庫。
由于二進制兼容在內核中的實現,Kylin操作系統可以支持絕大多數Linux應用;Kylin操作系統平臺可支持Linux標準RPM的應用程序安裝方式。這樣系統工具兼容只需要根據標準安裝LSB中規定的系統工具應用程序即可實現。如用戶/組管理工具等。
LSB規范中對文件系統組織結構有專門的規范,稱為文件層次規范(FHS)。采用該文件目錄組織方式,用戶在使用、生成、配置操作系統系統時與Linux完全相同。Kylin操作系統的Linux文件目錄組織結構主要涉及以下兩類文件:
Linux二進制應用:由于Kylin操作系統直接支持Linux二進制應用,故只要在路徑設置時符合Linux的缺省路徑設置,用戶就可以按與Linux環境相同的方式使用Linux二進制應用,無任何區別。
動態鏈接庫:Kylin操作系統通過可執行文件加載器中的動態鏈接庫路徑選項定義了Linux二進制應用的存放位置。為了支持Linux的文件目錄組織結構,Kylin操作系統的可執行文件加載器定義了缺省的加載路徑為“/”,加載器采用標準的ld_linux.so加載器。
Kylin操作系統上Linux二進制兼容的實現現狀和未來工作
目前, Kylin在I386體系結構的平臺上可以支持oracle數據庫、apache服務器等大型Linux應用程序;并且已經通過I386體系結構的系統上的LSB1.3標準測試;同時在IA64體系機構上實現了Linux兼容的基本功能,可以運行小規模的Linux程序。
Kylin上的Linux二進制兼容工作已經取得了較好的結果,我們將繼續針對I386體系結構在性能上作進一步的優化,并完善IA64上對Linux二進制兼容工作。