黃玉坤, 裴喜龍, 徐志宇, 王建民
1(江西財經(jīng)大學 信息管理學院, 南昌 330032)
2(同濟大學 電子與信息工程學院, 上海 200092)
3(中國科學院 軟件研究所, 北京100190)
近年來, 伴隨著云計算、物聯(lián)網(wǎng)、人工智能技術(shù)不斷進步, 智能設(shè)備迅速發(fā)展, 數(shù)據(jù)無處不在, 最終實現(xiàn)萬物互聯(lián). 移動終端和智能設(shè)備廣泛普及, 異構(gòu)計算開始興起, 邊緣計算應用爆發(fā)式增長[1,2]. 邊緣計算是物聯(lián)網(wǎng)中重要的一環(huán), 它將算力下沉到邊緣側(cè), 大大減少云端算力壓力, 節(jié)約帶寬, 且能快速響應端設(shè)備請求.面向萬物互聯(lián)的邊緣計算具有豐富的場景和應用[3,4],如何應對不同場景下對算力的差異化需求, 對邊緣計算平臺軟硬件體系的開放性、靈活性、可定制、可擴展性等方面提出了挑戰(zhàn).
在物聯(lián)網(wǎng)碎片化環(huán)境中, RISC-V架構(gòu)具有廣泛的發(fā)展前景. RISC-V是一種開源的指令集架構(gòu)(instruction set architecture, ISA), RISC-V指令集架構(gòu)的開放性、模塊化、高度可定制性的特點使得其成為體系結(jié)構(gòu)和軟件系統(tǒng)創(chuàng)新的理想實驗平臺[5,6]. RISC-V的發(fā)展十分迅速, 涌現(xiàn)了大量采用RISC-V指令集架構(gòu)的開源或商用處理器和SoC, 如鯤鵬、PulSAR等[7]; 除了硬件的微架構(gòu)設(shè)計、邏輯設(shè)計外, 在軟件生態(tài)方面也日漸成熟,如UCB提供了RISC-V的開源編譯器GCC、LLVM[8],開源仿真器Spike、QEMU, 社區(qū)也實現(xiàn)了支持RISC-V架構(gòu)的openEuler[9]開源操作系統(tǒng)和 FreeBSD、Debian等操作系統(tǒng)的移植. 在一個系統(tǒng)級的方案中, 芯片是核心和基礎(chǔ), 但構(gòu)筑在芯片之上的整個系統(tǒng)軟硬件方案,才是最終與應用直接接口的關(guān)鍵.
在邊緣計算領(lǐng)域中, 采用RISC-V架構(gòu)的操作系統(tǒng)無論是內(nèi)核的架構(gòu)還是應用組織的方式, 都在不斷的發(fā)生著創(chuàng)新和變化. openEuler是一個基于RISC-V指令集架構(gòu)的開源Linux發(fā)行版本, 具有開放、靈活、不斷演進和架構(gòu)包容的軟件生態(tài)體系. openEuler的目標是從系統(tǒng)軟件的角度, 打通不同算力, 讓開發(fā)者可以在其之上進行技術(shù)創(chuàng)新, 使其適應多樣性的計算場景,支撐邊緣側(cè)應用的運行需求. 因此, 基于RISC-V指令集架構(gòu)的openEuler操作系統(tǒng)是一個很好的構(gòu)建邊緣計算應用的創(chuàng)新平臺.
然而, 邊緣計算應用對底層軟件工具鏈的要求也非常高, 包括對一些主流的算法庫和程序開發(fā)框架的支持, 這對上層開發(fā)者的使用體驗以及市場的接受度和認可度有直接的影響. 理想狀態(tài)下, 應用開發(fā)者應該可以在無需了解芯片底層硬件的細節(jié)和指令集架構(gòu)的情況下進行應用程序的開發(fā), 這需要擴展操作系統(tǒng)功能、增強底層軟件開發(fā)環(huán)境和工具鏈. 另外, 不同的應用場景和應用模式, 對面向邊緣計算的軟件開發(fā)框架等基礎(chǔ)設(shè)施也提出了需求.
在云計算和邊緣計算的軟件架構(gòu)中, 廣泛采用了XaaS模式, 即Paas平臺即服務(wù)、IaaS基礎(chǔ)設(shè)施即服務(wù)、SaaS軟件即服務(wù)等模式. 在邊緣計算中實現(xiàn)面向XaaS的軟件架構(gòu)能夠?qū)⑦吘壎伺c云端進行融合. COMO(C++ component model)技術(shù)[10,11]是一個改進C++構(gòu)件技術(shù)的開源項目, 它可以將細粒度的計算(機器指令或軟件程序)抽象成構(gòu)件服務(wù), 并提供XaaS服務(wù)架構(gòu), 有利于對軟件系統(tǒng)在編譯階段和運行時的動態(tài)演進.
RISC-V架構(gòu)相比其他成熟的商業(yè)架構(gòu)的最大的不同在于它是一個模塊化的架構(gòu). ISA在CPU軟件和CPU硬件設(shè)計者之間, 提供了一個抽象層(接口).RISC-V架構(gòu)不僅短小精悍, 而且其不同的部分還能以模塊化的方式組織在一起, 從而試圖通過一套統(tǒng)一的架構(gòu)滿足各種不同的應用. 基于虛擬原型(virtual prototype)擴展和配置RISC-V是基于RISC-V的計算機系統(tǒng)開發(fā)的重要手段[12,13].
COMO技術(shù)可以在系統(tǒng)服務(wù)和軟件服務(wù)抽象的接口層面保持構(gòu)件的一致性. COMO同樣采用虛擬原型的設(shè)計方法, 把程序分為元數(shù)據(jù)和邏輯兩層, 元數(shù)據(jù)則是程序的原型抽象, 這一特性使得COMO構(gòu)件可以在支持RISC-V架構(gòu)的系統(tǒng)中與底層硬件的接口層保持統(tǒng)一的模塊化結(jié)構(gòu). 結(jié)合RISC-V架構(gòu)及openEuler的模塊化設(shè)計的技術(shù)特點, COMO提供了一個面向XaaS模式的ServiceManager軟件開發(fā)框架, 使得COMO可以在云計算、邊緣計算及其結(jié)合的應用場景提供一個統(tǒng)一的構(gòu)件化程序運行環(huán)境和開發(fā)模型. COMO在ISC-V指令集和openEuler操作系統(tǒng)上的系統(tǒng)架構(gòu)如圖1所示.

圖1 COMO在RISC-V指令集和openEuler操作系統(tǒng)上的系統(tǒng)架構(gòu)
本文的主要工作是在基于RISC-V架構(gòu)和openEuler操作系統(tǒng)的軟硬件平臺上移植COMO構(gòu)件程序運行與開發(fā)環(huán)境, 為面向云計算與物聯(lián)網(wǎng)的邊緣計算應用提供面向XaaS服務(wù)的構(gòu)件化程序開發(fā)模式; 并通過一個簡單的實例介紹COMO的ServiceManager框架在邊緣計算中的應用. 基于RISC-V和openEuler系統(tǒng)之上的QEMU模擬器進行了COMO運行與開發(fā)環(huán)境移植的實驗, 證明了COMO構(gòu)件技術(shù)與RISC-V指令集架構(gòu)和openEuler操作系統(tǒng)的兼容性和可行性. COMO構(gòu)件技術(shù)與RISC-V指令集系統(tǒng)和openEuler操作系統(tǒng)的結(jié)合, 為openEuler生態(tài)圈注入了新的特性和活力,同時, 借助RISC-V硬件技術(shù)和openEuler生態(tài)圈的發(fā)展, COMO構(gòu)件技術(shù)能夠獲得更多機會得到推廣和使用.
由于COMO、openEuler、RISC-V都處于研發(fā)的起步和發(fā)展階段, 從無到有地研發(fā)一個計算環(huán)境比開發(fā)一個應用要難得多. 在一個新的體系架構(gòu)的計算機上開發(fā)軟件系統(tǒng), 首先要在上面運行起較完整的開發(fā)環(huán)境, 本文采用openEuler的RISC-V鏡像作為實驗環(huán)境[14]. 目前支持“openEuler on RISC-V”的硬件平臺有:(1) NutShell (果殼, UCAS) COOSCA 1.0; (2) SiFive HiFive Unleashed. 然而現(xiàn)在RISC-V還不普及, 在實際的硬件平臺上進行移植工作之前, 利用RISC-V的QEMU進行COMO移植的仿真, 可以以較低的硬件成本和時間成本驗證COMO移植的可行性和COMO構(gòu)件在openEuler on RISC-V上運行的兼容性.
工作的第一步需要通過QEMU仿真出RISC-V硬件. 本文的實驗環(huán)境是X86的Ubuntu 18.04, 以及自己編譯RISC-V版的QEMU[15-17].
從官方資源庫下載openEuler RISC-V 移植版, 并通過wget下載互聯(lián)網(wǎng)資源.
通過下列命令啟動虛擬機.

$qemu-system-riscv64-nographic -machine virt-smp 8 -m 2G-kernel fw_payload_oe.elf-drive file=oe-rv-rv64g-30G.qcow2, format=qcow2, id=hd0-object rng-random, filename=/dev/urandom, id=rng0-device virtio-rng-device, rng=rng0-device virtio-blk-device, drive=hd0-device virtio-net-device, netdev=usernet-netdev user, id=usernet, hostfwd=tcp::12055-:22-append 'root=/dev/vda1 rw console=ttyS0 systemd.default_timeout_start_sec=600 selinux=0 highres=off mem=4096M earlycon'
RISC-V沒有X86平臺上的基本輸入輸出系統(tǒng)BIOS, 所以openEuler操作系統(tǒng)的引導加載程序是基于OpenSBI項目的OpenSBI RISC-V, 后者實現(xiàn)了Supervisor二進制接口[18]. 如果虛擬機正常工作, 則顯示結(jié)果如圖2所示. RISC-V上openEuler成功啟動后的界面如圖3所示.

圖2 qemu-system-riscv64起動界面

圖3 RISC-V上openEuler啟動成功
COMO的組成部分包括: (1)工具部分, C++構(gòu)件化需要的構(gòu)件定義語言(componentdefinition language,CDL)編譯器cdlc、構(gòu)件編譯環(huán)境; (2)與Java基礎(chǔ)類庫對應的Libcore核心庫. openEuler在RISC-V上的基礎(chǔ)類庫支持不夠完整, 所以這里把第2部分做了部分裁剪. 這樣做的好處是能得到一個精簡的COMO, 使得精簡COMO可以在計算能力更弱的環(huán)境中運行. 下面以RISC-V為開發(fā)機, 進行本地編譯.
一個軟件, 如果能在與目標機體系結(jié)構(gòu)及操作系統(tǒng)等硬件、軟件一致的環(huán)境中編譯自己, 那比較容易實現(xiàn)開發(fā)、調(diào)試、測試的集成化. 可是openEuler在RISC-V上還很弱小, 這個環(huán)境的可安裝包也不完整,于是只能從編譯COMO所需要的環(huán)境開始構(gòu)建, 即以RISC-V為開發(fā)機, 進行本地編譯, 除了cmake, 其它COMO所依賴工具都是從源碼開始構(gòu)建的.
從源碼開始安裝cmake, 遇到了C/C++編譯器版本上的問題. 通過驗證, 這個問題可以在openEuler發(fā)行版上解決, 從源頭治理一個生態(tài)往往成本是最小的,解決軟件包(庫)的版本依賴是所有操作系統(tǒng)開發(fā)商都要面對的困難. 最后決定從openEuler的發(fā)行軟件包中安裝cmake.
通過yum安裝cmake等軟件時, 遇到了“Cannot download repomd.xml”錯誤, 這是軟件的安裝源有問題引起的, 可以用非正式(preview)的源, 并在.repo文件中加sslverify=0解決.

/etc/yum.repos.d/oe-rv.repo[base]name=base baseurl=https://isrc.iscas.ac.cn/mirror/openeuler-sig-riscv/oe-RISCV-repo/enabled=1 gpgcheck=0 sslverify=0
在git clone COMO源碼倉庫時, 遇到“SSL certificate problem”問題, 可通過下列命令解決.
git config --global http.sslVerify false
在“openEuler on RISC-V”環(huán)境中編譯COMO, 選COMO本地Linux編譯環(huán)境: como_linux_riscv64.
由于COMO倉庫中缺省的構(gòu)件描述語言編譯工具cdlc是面向openEuler X86平臺的, 所以在編譯COMO前, 首先要編譯出COMO工具鏈, 所用的COMO環(huán)境是: Comotools.
在Comotools環(huán)境中編譯完成cdlc后, 發(fā)布cdlc工具鏈:
cp ./out/host/como/tools/cdlc/cdlc ./tools/cdlc
編譯COMO前, 需要安裝并配置dbus開發(fā)包.
$yum install dbus-devel
$ cp ./lib64/dbus-1.0/include/dbus/dbus-arch-deps.h/usr/include/dbus-1.0/dbus
在搭建完成openEuler on RISC-V和COMO的build環(huán)境之后, 下一步的工作是COMO的代碼移植.
將COMO代碼移植到openEuler平臺上需要關(guān)注以下問題.
(1) ELF格式的約定
openEuler是一種Linux操作系統(tǒng), 它的可執(zhí)行文件及動態(tài)鏈接庫等二進制文件是ELF格式的, COMO的元數(shù)據(jù)存放在ELF格式文件的“.metadata”段中, 所以COMO在openEuler上沒有發(fā)行文件格式上的問題.
COMO采用與Java類似的元數(shù)據(jù)與代碼編譯結(jié)果放在一起的發(fā)行方式, 構(gòu)件存儲為ELF格式文件. 傳統(tǒng)的基于PE/ELF可執(zhí)行文件格式的線性符號表導出為標志的軟件運行時資源共享機制, 在計算能力已經(jīng)大大發(fā)展的時代, 顯得臃腫. COMO的類、接口、方法等定義信息是通過元數(shù)據(jù)表達的, 不產(chǎn)生導出符號, 所以其發(fā)行文件的導出符號表很簡潔.
(2) RISC-V EABI參數(shù)對齊
各種約定的一致性是評價一個操作系統(tǒng)成熟度的重要指標. COMO代碼中, 反射機制構(gòu)造調(diào)用棧的一段匯編代碼是與平臺相關(guān)的, 它要求把從RPC等渠道得到的COMO方法調(diào)用參數(shù), 遵守RISC-V ABI規(guī)范形成調(diào)用棧. ABI定義了調(diào)用C/C++程序傳參數(shù)方法.
嵌入式系統(tǒng)上的RISC-V的ABI標準是EABI,Linux上的RISC-V的ABI標準是UABI[19,20]. COMO采用了RISC-V EABI參數(shù)對齊規(guī)則: 如果參數(shù)可以完全放在寄存器內(nèi), 則放在寄存器內(nèi), 否則把寄存器內(nèi)擺放不下的參數(shù)放在棧里. 無論參數(shù)是在寄存器里, 還是在棧上, 所有參數(shù)傳遞時要數(shù)據(jù)對齊. XLEN這個參數(shù)是指數(shù)據(jù)總線寬度, 可能的值是32或64.
1)對于XLEN=32的系統(tǒng), 數(shù)據(jù)總線寬度8 B.
2)對于XLEN=64的系統(tǒng), 數(shù)據(jù)總線寬度16 B.
EABI函數(shù)調(diào)用參數(shù)所用寄存器, 如表1所示. 浮點數(shù)參數(shù)也通過整數(shù)寄存器(x10-x11、x12-x17)或者棧傳遞.

表1 EABI函數(shù)調(diào)用參數(shù)所用寄存器
(3) COMO在RISC-V上的移植
COMO是采用C++ 11 (-std=gnu++11)標準實現(xiàn)的, 但有少部分用匯編寫的程序是與計算機體系結(jié)構(gòu)相關(guān)的, 以下代碼需要用RISC-V匯編重寫:

?
另外還需要創(chuàng)建一個RISC-V的CMake編譯腳本文件:
build/como_linux_riscv64.cmake
為了驗證COMO構(gòu)件技術(shù)在RISC-V指令集架構(gòu)和openEuler操作系統(tǒng)上的兼容性、可行性和實用性,搭建基于RISC-V和openEuler上的QEMU模擬器的實驗環(huán)境并實現(xiàn)COMO技術(shù)的移植, 利用COMO的協(xié)同計算能力, 組成一個邊緣計算集群, 實現(xiàn)多臺RISC-V節(jié)點協(xié)同計算, 實驗軟硬件架構(gòu)如圖4所示.

圖4 COMO技術(shù)的ServiceManager框架實現(xiàn)集群式RISC-V協(xié)同計算
COMO構(gòu)件技術(shù)能夠方便實現(xiàn)程序框架模型, 但它本身不強調(diào)對某一框架的支持. ServiceManager是COMO面向服務(wù)的開發(fā)框架之一. ServiceManager提供了Server的Name和Handle之間對應關(guān)系的查詢能力, 它主要包含的功能: (1) 注冊, 當一個 Server 創(chuàng)建后, 應該將這個 Server 的 Name 和 Handle 對應關(guān)系記錄到 ServiceManager 中. (2) 查詢, 其他應用可以根據(jù)Server 的 Name 查詢到對應的 Service Handle.
為了驗證“openEuler on RISC-V”的網(wǎng)絡(luò)通信能力,基于IP通信, 實現(xiàn)了一個COMO ServiceManager版本的應用程序, 該程序位于COMO源碼中的samples/democomponent目錄, 由Client和Component兩部分組成. Component實現(xiàn)了一個COMO構(gòu)件, Client實現(xiàn)了如何對這個構(gòu)件進行調(diào)用. 類似于OSGi, Service-Manager框架實現(xiàn)了一個優(yōu)雅、完整和動態(tài)的組件模型, 構(gòu)件無需重新引導就可以被遠程安裝、啟動、升級和卸載. 本實驗中, 客戶端和服務(wù)管理程序都運行在Master結(jié)點, 服務(wù)提供者運行在Workers結(jié)點, 通過FindService找到COMO構(gòu)件的服務(wù), 不需要知道它的提供者在哪個結(jié)點運行, 就可以調(diào)用它的服務(wù).
運行起來的COMO示例程序效果如圖5所示, 這個示例演示了一個宿主程序通過反射機制調(diào)用COMO構(gòu)件編寫的服務(wù)組件的過程.

圖5 COMO示例的運行結(jié)果
隨著云計算、物聯(lián)網(wǎng)等技術(shù)的興起和廣泛應用,邊緣計算作為云計算的補充和延伸, 可充分利用邊緣算力. 但是, 邊緣計算因為其條件受限的軟硬件部署限制, 對服務(wù)器在環(huán)境適配性、程序運行環(huán)境的部署和程序運行的效率上有更嚴苛要求. 面對海量邊緣應用場景, 硬件指令集架構(gòu)ISA、軟件基礎(chǔ)平臺的操作系統(tǒng)和其上的軟件開發(fā)框架、程序編譯、運行的工具鏈等基礎(chǔ)設(shè)施尤為重要.
本文完成了基于RISC-V和openEuler上的QEMU模擬器的實驗環(huán)境搭建和COMO運行與開發(fā)環(huán)境的移植, 證明了COMO構(gòu)件技術(shù)與RISC-V指令集架構(gòu)和openEuler操作系統(tǒng)的兼容性和可行性. 實驗應用實例表明, 在一個以RISC-V指令集架構(gòu)和openEuler操作系統(tǒng)為軟硬件平臺的集群上可以成功運行COMO構(gòu)件技術(shù)和其所支持的ServiceManager框架編寫的面向服務(wù)的應用程序, 為云計算和物聯(lián)網(wǎng)為主要應用場景的邊緣計算提供了一個簡單、有效和可行的面向XaaS計算模式, 以及一個與C++語言無縫銜接的構(gòu)件化程序設(shè)計開發(fā)模式.
由于現(xiàn)在RISC-V的發(fā)展還不夠成熟, 不能完全靠RISC-V環(huán)境把COMO完整編譯出來, 因此提供交叉編譯支持就很必要. 本文下一步的工作方向是, 嘗試使用Clang/LLVM編譯器, 把COMO裁成多個比較小的模塊集合. 但這個嘗試目前還處于交叉編譯環(huán)境定義階段. 隨著交叉編譯環(huán)境的完善, 逐步發(fā)現(xiàn)openEuler上Clang/LLVM應該做的工作. Clang/LLVM是現(xiàn)在使用較多的編譯器[21], 所以這個嘗試是很有意義的.
希望COMO能在這個新的工具鏈建設(shè)中發(fā)揮一定作用, 并在與openEuler與RISC-V社區(qū)共同發(fā)展的過程中壯大自己.