趙正旭,徐 棚,張慶海
1(青島理工大學 機械與汽車工程學院,青島 266525)
2(石家莊鐵道大學 信息科學與技術(shù)學院,石家莊 050043)
基于Linux 內(nèi)核的國產(chǎn)操作系統(tǒng)發(fā)行版眾多,卻沒有一款操作系統(tǒng)完全取代微軟桌面系統(tǒng).根本原因是國產(chǎn)操作系統(tǒng)的軟件生態(tài)資源匱乏,軟件種類不全面,數(shù)量不充足導致[1].為擴大國產(chǎn)操作系統(tǒng)的應(yīng)用軟件資源,文獻[1-3]介紹了在國產(chǎn)操作系統(tǒng)NeoKylin環(huán)境中部署第三方開源軟件的傳統(tǒng)方法.但是由于Linux 操作系統(tǒng)中開源軟件依賴問題,大部分開源軟件無法通過傳統(tǒng)的軟件部署方法安裝,因此軟件依賴問題是主要關(guān)注點.
開源軟件依賴關(guān)系的問題來源于操作系統(tǒng)中的函數(shù)庫文件.函數(shù)庫是為實現(xiàn)某種特定功能而編譯好的代碼或數(shù)據(jù),以文件的形式存在操作系統(tǒng)上,是操作系統(tǒng)的重要組成部分.Windows 或Linux 操作系統(tǒng)中有著大量的函數(shù)庫文件,函數(shù)庫被應(yīng)用程序調(diào)用,應(yīng)用軟件的運行要依賴很多函數(shù)庫文件[4].
Windows 作為商業(yè)系統(tǒng)其基礎(chǔ)函數(shù)庫相對固定,第三方軟件在此環(huán)境中開發(fā),部署過程中不會有問題.Linux 系統(tǒng)庫函數(shù)文件分為靜態(tài)庫和動態(tài)庫.靜態(tài)庫在軟件開發(fā)過程中會被包含在生成的二進制文件中.共享庫在程序編譯時指定,程序運行時調(diào)用,不被包含在軟件的二進制文件中.而且開源平臺上的軟件一般依賴第三方函數(shù)庫開發(fā),從而形成軟件依賴關(guān)系.所以在國產(chǎn)操作系統(tǒng)中部署第三方軟件時會出現(xiàn)找不到依賴函數(shù)庫的問題[5].
隨著容器技術(shù)的發(fā)展,docker 容器技術(shù)能夠解決軟件依賴問題,但其主要被用來運行字符界面程序.針對GUI 應(yīng)用程序但不僅限于第三方GUI 應(yīng)用程序,本文的主要工作是:(1)分析GUI 應(yīng)用程序并將其部署在docker 鏡像內(nèi);(2)配置docker 容器與主機共享Linux系統(tǒng)圖形界面服務(wù),并根據(jù)GUI 應(yīng)用程序?qū)τ布Y源的要求,配置容器與主機共享顯卡等驅(qū)動程序.
在眾多國產(chǎn)操作系統(tǒng)中,以具有代表性的NeoKylin(中標麒麟) 操作系統(tǒng)為例,基于Linux 內(nèi)核開發(fā),是2010年國家核高基項目重點扶持的基礎(chǔ)軟件之一.當前該桌面系統(tǒng)最新版本為V7.0,采用Linux 3.10 內(nèi)核.針對x86和國產(chǎn)CPU 平臺自主開發(fā),打造具有安全可靠和自主可控等特性的國產(chǎn)操作系統(tǒng).NeoKylin 桌面版操作系統(tǒng)獨特的界面設(shè)計使其操作簡單方便,系統(tǒng)內(nèi)置滿足日常辦公的應(yīng)用軟件[6].但是官方提供的應(yīng)用軟件資源,無法滿足用戶的日常需求.在NeoKylin 上安裝其他Linux 發(fā)行版的軟件,通常會因為軟件依賴問題,無法安裝運行.應(yīng)用軟件資源匱乏,嚴重制約國產(chǎn)操作系統(tǒng)的發(fā)展.
容器技術(shù)(Linux container)中的容器通常被理解為集裝箱,它把應(yīng)用程序及程序運行的環(huán)境封裝在容器內(nèi)部,實現(xiàn)應(yīng)用程序在容器中運行[7].在容器的發(fā)展當中,docker 容器發(fā)展較快其技術(shù)也相當成熟,被視為容器的代表[8].Docker 容器支持應(yīng)用打包功能,把應(yīng)用程序運行需要的依賴程序和庫打包在鏡像中,應(yīng)用程序就能夠在docker 容器中穩(wěn)定的執(zhí)行程序.容器是docker 運行鏡像后產(chǎn)生的實體,容器被創(chuàng)建后可以執(zhí)行暫停和銷毀等操作.容器可看作宿主機上的進程,某一個容器出現(xiàn)宕機問題不會影響其他容器的正常運行.雖然容器之間相互隔離,但是無論在同一臺宿主機還是在不同宿主機上的容器可以通過IP 地址或者link機制等其他方式實現(xiàn)容器之間的相互通信[9].Docker運行架構(gòu)如圖1所示.
圖1 Docker 容器架構(gòu)
封裝后的鏡像可以放在任意docker的主機上運行,docker 利用鏡像創(chuàng)建容器從而使用容器里的應(yīng)用程序,而容器內(nèi)部應(yīng)用程序運行完全不依賴主機的運行環(huán)境.封裝后的鏡像可以放在任意安裝docker的主機上運行,docker 利用鏡像創(chuàng)建容器從而使用容器里的應(yīng)用程序[10].所以對于應(yīng)用程序,使用容器技術(shù)部署應(yīng)用軟件比傳統(tǒng)軟件部署方式更有實際意義.
X11是X 協(xié)議的第11 個版本,也叫做X Window System,是一種以位圖顯示的網(wǎng)絡(luò)透明化窗口系統(tǒng)[11].X11 標準是開發(fā)可攜性圖形界面的工業(yè)軟件標準,它有一個重要的特性是與設(shè)備無關(guān)結(jié)構(gòu),任何支持X11協(xié)議的硬件,就能執(zhí)行應(yīng)用程序,顯示圖形界面窗口,這種特性使得根據(jù)X11 標準開發(fā)的應(yīng)用程序,可運行在不同環(huán)境下(個人電腦、大型計算機)[12].
X11是Linux 圖形界面環(huán)境的基礎(chǔ),Linux 本質(zhì)是命令行操作系統(tǒng),而X11 作為應(yīng)用程序運行在Linux操作系統(tǒng)的應(yīng)用層,為操作系統(tǒng)提供圖形界面顯示服務(wù).X11 基于C/S 架構(gòu)如圖2所示,包括X server、X client和X protocol.X client是客戶端是運行在Linux 系統(tǒng)上的應(yīng)用程序,X server是服務(wù)端,運行在顯示設(shè)備主機上,X protocol是客戶端和服務(wù)端的通信協(xié)議.
圖2 X11 架構(gòu)
Equalizer 一個成熟的并行渲染框架,它提供了大量的特性、算法和系統(tǒng)集成廣泛的現(xiàn)實世界研究和工業(yè)應(yīng)用[13].Equalizer 提供編譯運行方式的Linux 系統(tǒng)有Ubuntu 16.04和RHEL 6.8[14],要編譯運行Equalizer需要安裝大量的軟件依賴庫,NeoKylin 雖然基于Linux操作系統(tǒng),但官方提供的軟件完全不足以編譯運行Equalizer.NeoKylin 使用三方軟件,配置Equalizer 編譯運行環(huán)境,需要進行復(fù)雜的工作,第三方軟件還可能與系統(tǒng)自帶軟件沖突導致系統(tǒng)崩潰.Equalizer作為渲染框架,在NeoKylin 操作系統(tǒng)需要Linux 圖形界面服務(wù)X11的支持,對軟件運行環(huán)境的穩(wěn)定性要求較高,并且需要使用GPU 等硬件.因此以Equalizer為目標對象,進行獨立GUI 應(yīng)用的實驗論證.
Docker 鏡像是容器運行的實例,鏡像為容器提供文件系統(tǒng)資源.Docker 鏡像都是由基礎(chǔ)鏡像制作而成,而基礎(chǔ)鏡像是一般都是Linux 發(fā)行版的docker 鏡像,例如Ubunut、Fedora 等.
Linux 操作系統(tǒng)由內(nèi)核空間和用戶空間組成.內(nèi)核空間是kernel,Linux 操作系統(tǒng)啟動時會加載bootfs 文件系統(tǒng),bootfs 引導kernel 加載完成后就被卸載掉.Rootfs是用戶空間的文件系統(tǒng),rootfs 通常包含的是操作系統(tǒng)運行所需的文件系統(tǒng)如/dev、/proc、/bin 等標準目錄.對于不同的Linux 發(fā)行版,其bootfs 基本一致,rootfs不同.
Docker 鏡像采用分層的方式構(gòu)建,每一個鏡像都是由一層一層union 文件系統(tǒng)疊加組成.Docker的基礎(chǔ)鏡像的文件系統(tǒng)分為bootfs和rootfs 兩層,最底端是引導文件系統(tǒng)bootfs,在bootfs 之上的一層是rootfs.Docker 架構(gòu)下,沿用Linux 中rootfs 思想.當docker daemon為docker 容器掛載rootfs的時候,與傳統(tǒng)Linux內(nèi)核類似,將其設(shè)定為只讀模式.在rootfs 掛載完畢后,與Linux 內(nèi)核不同的是,docker daemon 沒有將docker容器的文件系統(tǒng)設(shè)為讀寫模式,而是利用union mount的技術(shù),在這個只讀的rootfs 之上再掛載一個讀寫的文件系統(tǒng),掛載時該讀寫文件系統(tǒng)內(nèi)空無一物.可以把docker 基礎(chǔ)鏡像創(chuàng)建容器的文件系統(tǒng)理解為:只含只讀的rootfs和可讀寫的文件系統(tǒng).
容器與主機共享kernel,擁有獨立的rootfs,包含一個操作系統(tǒng)所必須的庫文件及軟件管理工具,在容器內(nèi)部部署軟件與主機系統(tǒng)環(huán)境無關(guān).因此docker 容器能夠解決軟件依賴問題.
接下來就是制作鏡像,把軟件及相關(guān)依賴程序打包在鏡像內(nèi)部制作成獨立的軟件鏡像.Docker 制作鏡像的方法有兩種:手動制作和dockerfile 制作.一般情況下使用dockerfile 制作鏡像,但是基礎(chǔ)鏡像只包含操作系統(tǒng)基本函數(shù)庫文件,軟件需要的一些未知三方庫無法通過管理工具安裝,只能根據(jù)錯誤提示查找,所以先通過手動制作鏡像,再把制作鏡像的過程寫成dockerfile或者shell 腳本實現(xiàn)自動制作鏡像.
國產(chǎn)操作系統(tǒng)NeoKylin 采用X11 提供圖形桌面環(huán)境,其X server 版本號為1.19.3,X server在應(yīng)用層負責接收鍵盤和鼠標的輸入.GUI 應(yīng)用程序作為X client,包含X lib和X protocol.X lib是X client的C 語言接口庫,封裝了X protocol,主要提供X protocol的存取能力.X server 運行在連接顯示屏的主機上,X server接收并處理來自X client的請求,在屏幕上繪制圖形.
在NeoKylin 中,X11 通過DISPLAY 環(huán)境變量指定圖形顯示的屏幕窗口.DISPLAY的格式是[unix:端口]或[主機名:端口],前者表示使用本地的unix 套接字,后者表示使用TCP 套接字.X11 服務(wù)端默認配置是服務(wù)端監(jiān)聽本地的[unix:0]端口,DISPLAY的默認值為0.當系統(tǒng)運行GUI 程序后,程序會通過本地的Unix套接字與X server 通信,然后X server在當前主機屏幕繪制圖形界面.
鏡像內(nèi)部打包的GUI 應(yīng)用程序,在主機屏幕顯示圖形界面,需要實現(xiàn)GUI 應(yīng)用程序透過容器的隔離機制與主機的X server 通信.Docker 提供了一種機制,能夠?qū)崿F(xiàn)把主機上的某個目錄與容器的某個目錄(掛載點)關(guān)聯(lián)起來,容器內(nèi)掛載點下的文件就是主機系統(tǒng)目錄下的文件,類似Linux 操作系統(tǒng)下的mount 機制.通過掛載文件的方式,使主機與容器共享Unix 套接字,實現(xiàn)容器內(nèi)部的應(yīng)用程序與X server 通信.
Docker 基于基礎(chǔ)鏡像打包GUI 軟件制作獨立的GUI 應(yīng)用軟件鏡像.軟件鏡像創(chuàng)建容器,該容器可以看作獨立運行GUI 應(yīng)用程序.實際上GUI 應(yīng)用程序是在docker 容器內(nèi)運行,因為容器的隔離特性,GUI 應(yīng)用程序不能直接與主機上的X server 通信.主機上GUI 程序都是通過套接字實現(xiàn)與X server 互傳信息,所以利用docker 文件掛載機制把主機上的套接字文件掛載到容器內(nèi)部,實現(xiàn)主機和容器共享套接字.容器內(nèi)部的第三方GUI 應(yīng)用程序作為X client,通過套接字與主機的X server 通信,X server 把GUI 應(yīng)用程序的圖形界面繪制在屏幕上.最終實現(xiàn)GUI 應(yīng)用軟件在國產(chǎn)操作系統(tǒng)環(huán)境中運行.系統(tǒng)的整體架構(gòu)如圖3所示.
圖3 系統(tǒng)整體架構(gòu)
Equalizer是開源渲染框架,在Github 上公布的源碼,提供了Linux、Mac OS和Windows 三種編譯方式.本文利用docker 容器做封裝工具,選擇Linux 發(fā)行版Ubuntu16.04 系統(tǒng)鏡像,把Equalizer 編譯并封裝在鏡像中.獨立的應(yīng)用程序(應(yīng)用程序和程序運行環(huán)境)占用計算機的存儲空間,在制作鏡像時要選擇占用存儲空間較小的鏡像.獨立的GUI 應(yīng)用程序制作步驟如下:
(1)以Ubuntu16.04的鏡像為基礎(chǔ)鏡像,使用docker創(chuàng)建容器.在創(chuàng)建容器時注意通過在啟動命令中添加--gpus all 參數(shù),把配置好的Nvidia 驅(qū)動共享給容器.
(2)進入容器命令行,按照官方網(wǎng)站給出的Equalizer編譯環(huán)境配置方法操作,配置Equalizer的編譯環(huán)境.
(3)下載Equalizer 源代碼,執(zhí)行編譯命令.
(4)進入編譯后的/bin 文件夾執(zhí)行示例,驗證結(jié)果.
(5)docker commit 命令,永久保存容器,生成鏡像,方便下次使用.
Equalizer 封裝成鏡像之后,作為獨立的GUI 應(yīng)用使用.為方便使用,鏡像創(chuàng)建容器時調(diào)用容器內(nèi)部shell腳本,執(zhí)行容器內(nèi)部的應(yīng)用程序.
NeoKylin 操作系統(tǒng),采用Xorg 實現(xiàn)X11 協(xié)議,Xorg提供X server 服務(wù),當系統(tǒng)內(nèi)有程序運行時,程序會與X server 通信,X server 接收鼠標、鍵盤的輸入和管理屏幕輸出.Docker 內(nèi)部運行的程序要在屏幕上顯示界面,應(yīng)用程序就必須要與X server 通信.
基于國產(chǎn)操作系統(tǒng)上GUI 應(yīng)用程序的圖形界面展示原理,采用主機與容器共享X11的Unix 套接字的方式,實現(xiàn)X client的內(nèi)容從容器內(nèi)部傳遞到主機上的X server.把主機上的套接字目錄掛載到容器內(nèi)部,實現(xiàn)主機和容器共享Unix 套接字.
主機上套接字文件在tmp 文件夾中,將其掛載到容器內(nèi)部,-v/tmp/.X11-unix:/tmp/.X11-unix,實現(xiàn)主機和容器共享套接字目錄.啟動程序后,底層封裝的Xlib(C 語言接口庫)通過共享unix 套接字,傳遞信息給X server.X server 代碼運行,main 函數(shù)進入一個循環(huán).每次循環(huán)都包含,初始化、處理X client 信息和退出.最后X server 根據(jù)X client 發(fā)送的請求,在主機顯示器上繪制圖形界面.
本章節(jié)主要通過具體實驗,驗證在國產(chǎn)操作系統(tǒng)環(huán)境中方案實施的可行性.
實驗平臺的計算機軟件和硬件配置信息如表1所示,主要包括:CPU、內(nèi)存、顯卡、系統(tǒng)、內(nèi)核和容器版本信息.
表1 實驗軟硬件環(huán)境
實驗環(huán)境配置的軟件包含:Nvidia 顯卡驅(qū)動、docker、Nvidia-container-toolkit 工具包.
在NeoKylin 系統(tǒng)上安裝Linux 版本的Nvidia驅(qū)動,驅(qū)動要與顯卡型號匹配,否則會安裝失敗.在安裝之前,禁用系統(tǒng)默認的驅(qū)動,要把系統(tǒng)運行級別更改為文本模式.使用chmod 命令設(shè)置驅(qū)動程序可執(zhí)行權(quán)限,再進行安裝.
NeoKylin 操作系統(tǒng)上安裝docker 無法直接安裝,直接下載rpm 包強制安裝也無法運行,因為官方源中沒有提供安裝docker的依賴包.首先需要給NeoKylin操作系統(tǒng)換源,更換centos7的源,然后引入docker 源,直接yum 下載安裝.Linux 系統(tǒng)下,應(yīng)用程序穩(wěn)定運行的基礎(chǔ)就是依賴庫文件齊全.Yum 安裝docker 組件docker-ce、docker-ce-cli、containerd.io 時,操作系統(tǒng)僅提示安裝container-seLinux 依賴和升級libseccomp 依賴軟件.系統(tǒng)能安裝的依賴軟件是保存在文件夾的庫文件對系統(tǒng)不會有影響,重點關(guān)注升級的依賴.Libseccomp包為Linux 內(nèi)核的系統(tǒng)調(diào)用過濾機制提供了一個易于使用且獨立于平臺的接口,根據(jù)軟件向下兼容的特性,使其版本的升級對系統(tǒng)無影響.依賴庫文件配置齊全,docker 應(yīng)用在NeoKylin 系統(tǒng)中即可穩(wěn)定運行.
Equalizer是一個渲染框架,需要用到Nvidia 顯卡,安裝Nvidia-container-toolkit 工具包,使docker 內(nèi)部能夠調(diào)用Nvidia 驅(qū)動程序.安裝方法參考Nvidiadocker 網(wǎng)站提供的安裝說明[15],網(wǎng)站并沒有提供針對NeoKylin 操作系統(tǒng)的工具包,可使用CentOS7的工具包替代.
NeoKylin 操作系統(tǒng),Xhost 命令是X server的訪問控制工具.在當前桌面顯示docker 容器內(nèi)的GUI 應(yīng)用程序,需要對X server 設(shè)置,允許docker 內(nèi)部的GUI程序在顯示器上顯示.終端執(zhí)行Xhost +,授予每個用戶訪問X server的權(quán)限.
以上是整個實驗環(huán)境的配置,完成以上設(shè)置后,使用docker 制作Equalizer 渲染框架的鏡像.
NeoKylin 環(huán)境中制作GUI 應(yīng)用程序鏡像并運行步驟是:(1)基于Ubuntu16.04 鏡像創(chuàng)建容器,創(chuàng)建命令中配置掛載X11的Unix 套接字,并引入顯卡驅(qū)動程序;(2)在容器內(nèi)部安裝部署Equalizer;(3)容器內(nèi)運行Equalizer 程序,測試啟動是否正常;(4)主機內(nèi)執(zhí)行命令,Equalizer 鏡像創(chuàng)建容器并自動運行Equalizer.
編寫shell 腳本,自動配置以上操作.主要包括以下4 個腳本:
1)腳本Run.sh在主機上運行,負責運行ubuntu16.04鏡像創(chuàng)建容器,主要內(nèi)容如下(#后為注釋):
-v/tmp/.X11-unix:/tmp/.X11-unix #設(shè)置主機與容器共享套接字
-gpus all #設(shè)置容器與主機共享顯卡驅(qū)動
2)腳本Equalizer.sh在容器內(nèi)部運行,負責編譯Equalizer 源碼,主要內(nèi)容如下:
apt-get install … #安裝編譯環(huán)境
git clone … #下載源碼
ninja #編譯
3)腳本Init.sh在容器內(nèi)部運行,負責啟動Equalizer可執(zhí)行文件,主要內(nèi)容如下:
cd/Equalizer/build/bin/#進入編譯后的文件目錄
./eqPly #執(zhí)行可執(zhí)行文件
4)腳本EqualizerRun.sh在主機上運行,負責啟動容器內(nèi)部GUI 程序,主要內(nèi)容如下:
-v/tmp/.X11-unix:/tmp/.X11-unix #設(shè)置主機與容器共享套接字
-v/Equalizer:/Equalizer#主機與容器共享文件夾
-e DISPLAY=unix$DISPLAY #設(shè)置主機顯示屏
-gpus all #共享顯卡驅(qū)動
Docker 運行Equalizer 框架鏡像,使用分布式渲染時,容器和主機要設(shè)置IP和端口號,因為分布式渲染是通過網(wǎng)絡(luò)實現(xiàn)通信.
在NeoKylin 操作系統(tǒng)中直接配置Equalizer 編譯安裝環(huán)境,由于官方源提供的軟件不足以配置Equalizer的編譯環(huán)境,所以下載相關(guān)依賴軟件源碼編譯安裝,而該軟件又依賴其他軟件,整個過程陷入一個循環(huán)之中.在安裝軟件過程中,因為第三方依賴軟件問題多次導致系統(tǒng)無法啟動,未能成功安裝編譯.
Equalizer 渲染框架源碼大小100.9 MB.在容器內(nèi)配置編譯環(huán)境需要安裝的軟件及相關(guān)依賴庫共394 個,需要269 MB 存儲空間,安裝完成使用978 MB的額外磁盤空間.源碼編譯完成后制作的鏡像為2.82 GB,導出鏡像包為2.68 GB.
為測試容器內(nèi)Equalizer 程序的穩(wěn)定性,對其進行壓力測試.使用兩個節(jié)點渲染,增加渲染模型的大小比較模型加載時間和渲染的幀率.實驗數(shù)據(jù)如表2所示.
表2 Equalizer 渲染不同模型產(chǎn)生的數(shù)據(jù)
實驗結(jié)果表明,在NeoKylin 環(huán)境中使用docker 容器運行Equalizer 渲染的模型越大,加載時間越久,幀率降低.雖然總體渲染效率下降,在該環(huán)境下Equalizer不僅能夠?qū)?.4 MB的小模型進行渲染,而且能夠渲染1.05 GB的大模型,證明其具有穩(wěn)定性,也表明在國產(chǎn)操作系統(tǒng)NeoKylin 環(huán)境中,使用docker 容器運行GUI應(yīng)用程序的方案是可行的.
本文對國產(chǎn)操作系統(tǒng)環(huán)境中制作并運行獨立GUI應(yīng)用程序進行探索,利用容器技術(shù)初步實現(xiàn)制作獨立GUI 應(yīng)用程序在國產(chǎn)操作系統(tǒng)上運行.結(jié)果表明在Neo-Kylin 國產(chǎn)操作系統(tǒng)上,使用docker 容器技術(shù),可以實現(xiàn)第三方GUI 應(yīng)用程序獨立運行.文中方案給國產(chǎn)操作系統(tǒng)兼容第三方GUI 應(yīng)用程序提供新思路,使用該方案可以增加國產(chǎn)操作系統(tǒng)的應(yīng)用軟件資源.但方案中還有許多細節(jié)問題需要研究,包括容器和主機共享文件的機制,完善容器技術(shù)或可解決國產(chǎn)操作系統(tǒng)軟件資源匱乏的問題,有助于加快國產(chǎn)操作系統(tǒng)的發(fā)展.