.NET適配HarmonyOS進(jìn)展的方法
1. 前言
目前國(guó)產(chǎn)化系統(tǒng)浪潮下,適配鴻蒙是中國(guó)軟件大勢(shì)所趨,.NET作為最適合開(kāi)發(fā)客戶端語(yǔ)言之一,適配鴻蒙系統(tǒng)(HarmonyOS Next)是目前.NET開(kāi)發(fā)者最關(guān)心的事情。我目前業(yè)余時(shí)間正在移植Avalonia到HarmonyOS,去年在.NET Conf CN上分享過(guò),目前又取得一點(diǎn)進(jìn)展,所以本文把所有問(wèn)題進(jìn)行整合與大家進(jìn)行分享。
2. 項(xiàng)目狀態(tài)
目前.NET可以成功在HarmonyOS Next上運(yùn)行。
Avalonia移植項(xiàng)目在真機(jī)上也可以運(yùn)行,本文主要探討.NET適配相關(guān)工作。
3. 運(yùn)行時(shí)
自HarmonyOS 5.0.0(12)起,禁止匿名內(nèi)存申請(qǐng)可執(zhí)行權(quán)限,除系統(tǒng)內(nèi)置的JavaScript引擎外,其他虛擬機(jī)不能使用Jit功能,所以無(wú)法將CoreCLR接入到鴻蒙系統(tǒng)中,而最新版的Mono雖然支持解釋執(zhí)行,但是由于性能問(wèn)題也不會(huì)接入Mono到鴻蒙系統(tǒng),最終只能選擇接入NativeAOT運(yùn)行時(shí)。
4. NativeAOT
支撐鴻蒙可以接入NativeAOT的原理是鴻蒙系統(tǒng)兼容libc是musl的Linux系統(tǒng)的動(dòng)態(tài)庫(kù)(.so)。而.NET的RID支持linux-musl-arm64/linux-musl-x64,所以理論上可以將.NET程序編譯為原生的Linux動(dòng)態(tài)庫(kù)(.so),然后在鴻蒙的原生項(xiàng)目中,通過(guò)dlopen以及dlsym等函數(shù)調(diào)用C#中的入口函數(shù)。
而C#調(diào)用鴻蒙api則通過(guò)P/Invoke調(diào)用鴻蒙的NDK,而ArkUI的TypeScript api則通過(guò)NDK中的napi調(diào)用。
具體做法可以參考我正在做的Avalonia移植項(xiàng)目: https://github.com/OpenHarmony-NET/OpenHarmony.Avalonia
5. 已知問(wèn)題
5.1 syscall限制 (已解決)
鴻蒙系統(tǒng)使用了seccomp限制危險(xiǎn)的syscall調(diào)用。標(biāo)準(zhǔn)posix下,如果系統(tǒng)不支持某個(gè)syscall則返回錯(cuò)誤碼,而seccomp非常激進(jìn),如果調(diào)用了非法的sycall則直接殺掉進(jìn)程。.NET的運(yùn)行時(shí)初始化時(shí),會(huì)調(diào)用__NR_get_mempolicy系統(tǒng)調(diào)用對(duì)numa支持進(jìn)行檢查,而這個(gè)系統(tǒng)調(diào)用不在鴻蒙的seccomp白名單中,所以導(dǎo)致直接宕機(jī)。
鴻蒙系統(tǒng)中seccomp的系統(tǒng)調(diào)用白名單如下:https://gitee.com/openharmony/startup_init/blob/master/services/modules/seccomp/seccomp_policy/app.seccomp.policy
其實(shí)安卓中也有類似的限制,.NET的NativeAOT之所以能在安卓平臺(tái)下運(yùn)行是因?yàn)?NET中對(duì)安卓進(jìn)行了特殊處理,而在鴻蒙平臺(tái)我們使用的是Linux平臺(tái)的代碼,所以沒(méi)有對(duì)這些系統(tǒng)調(diào)用進(jìn)行處理。
解決辦法則是自行修改代碼,將numa的函數(shù)全部修改為空函數(shù)。
5.2 mmap申請(qǐng)?zhí)摂M內(nèi)存過(guò)大(已解決)
解決上個(gè)問(wèn)題后,.NET運(yùn)行時(shí)初始化依然不能成功,導(dǎo)致程序崩潰,經(jīng)過(guò)排查發(fā)現(xiàn)是GC初始化時(shí)會(huì)申請(qǐng)256G左右的虛擬內(nèi)存,導(dǎo)致mmap返回Out Of Memory錯(cuò)誤。
解決辦法1:設(shè)置環(huán)境變量“DOTNET_GCHeapHardLimit”,將虛擬內(nèi)存申請(qǐng)控制在約180G以下即可。
解決辦法2:修改源代碼,將USE_REGIONS宏關(guān)掉。
5.3 ICU,OpenSSL等第三方庫(kù)缺失(已解決)
解決方案1:從Alpine上偷包 ,因?yàn)锳lpine的libc是musl,所以理論上Alpine的庫(kù)在鴻蒙上大部分都能使用。
阿里云Alpine軟件包鏡像地址:
arm64架構(gòu):https://mirrors.aliyun.com/alpine/edge/main/aarch64/amd64架構(gòu):https://mirrors.aliyun.com/alpine/edge/main/x86_64/
解決方案2:如果該庫(kù)有cmake項(xiàng)目,則可以通過(guò)鴻蒙的CMake工具鏈編譯。
5.4 ICU初始化失?。ㄒ呀鉀Q)
鴻蒙的ICU配置文件路徑與默認(rèn)路徑不同,需要調(diào)用修改環(huán)境變量API,將ICU_DATA修改為/system/usr/ohos_icu
且鴻蒙平臺(tái)上libICU的大版本是72,要使用這個(gè)版本的庫(kù)。
5.5 NativeAOT如何跨平臺(tái)編譯 (Windows平臺(tái)已解決)
NativeAOT眾所周知不支持跨平臺(tái)編譯,而我的方案需要發(fā)布到linux-musl平臺(tái),所以無(wú)法在Windows上發(fā)布,影響開(kāi)發(fā)效率。
解決方案:在項(xiàng)目中引入項(xiàng)目https://github.com/OpenHarmony-NET/PublishAotCross
5.6 無(wú)法調(diào)用Marshal.GetDelegateForFunctionPointer
相關(guān)函數(shù)
Marshal.GetDelegateForFunctionPointer的實(shí)現(xiàn)依賴動(dòng)態(tài)生成匯編,而HarmonyOS不支持動(dòng)態(tài)生成匯編代碼執(zhí)行(Jit),使用該函數(shù)會(huì)導(dǎo)致崩潰。
解決方案: 使用函數(shù)指針直接調(diào)用。
6. 如何修改NativeAOT代碼
前文中提到部分問(wèn)題的解決方案是修改源碼,具體操作步驟如下:
修改完代碼,執(zhí)行以下命令進(jìn)行編譯(linux平臺(tái)下,需要有編譯環(huán)境):
./build.sh --subset clr.aot --configuration Release -arch arm64 --cross |
編譯成功后,打開(kāi)目錄 運(yùn)行時(shí)/artifacts/bin/coreclr/linux.arm64.Release/aotsdk
,將這里所有的替換到自己電腦nuget的緩存目錄, 例如C:\Users\用戶名\.nuget\packages\runtime.linux-musl-arm64.microsoft.dotnet.ilcompiler\dotnet版本\sdk
7.相關(guān)鏈接
https://github.com/dotnet/runtime/issues/110074
https://github.com/dotnet/runtime/issues/111649
到此這篇關(guān)于.NET適配HarmonyOS進(jìn)展的文章就介紹到這了,更多相關(guān).NET適配HarmonyOS內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 鴻蒙HarmonyOS App開(kāi)發(fā)造輪子之自定義圓形圖片組件的實(shí)例代碼
- 快速入門HarmonyOS的Java UI框架的教程
- 詳解HarmonyOS簡(jiǎn)介
- 淺析鴻蒙基礎(chǔ)之Permanent 持久性內(nèi)存對(duì)象(HarmonyOS鴻蒙開(kāi)發(fā)基礎(chǔ)知識(shí))
- 鴻蒙開(kāi)發(fā)之處理圖片位圖操作的方法詳解(HarmonyOS鴻蒙開(kāi)發(fā)基礎(chǔ)知識(shí))
- HarmonyOS開(kāi)發(fā)基礎(chǔ)知識(shí)之Component和ComponentContainer區(qū)別(鴻蒙教程)
- 鴻蒙開(kāi)發(fā)之Button按鈕類型及如何通過(guò)代碼設(shè)置(HarmonyOS鴻蒙開(kāi)發(fā)基礎(chǔ)知識(shí))
- 鴻蒙HarmonyOS 分布式任務(wù)調(diào)度的實(shí)現(xiàn)
- 鴻蒙HarmonyOS開(kāi)發(fā):Navigation路由導(dǎo)航功能和實(shí)踐
- 在HarmonyOS工程中添加Module的方法
相關(guān)文章
在.Net?Framework應(yīng)用中請(qǐng)求HTTP2站點(diǎn)的問(wèn)題解析
隨著各大瀏覽器支持和蘋果的帶頭效應(yīng),HTTP2的應(yīng)用會(huì)越來(lái)越廣泛,但是規(guī)模龐大的.NET?Framework應(yīng)用卻也不能為了連接HTTP2就升級(jí)到NET?Core平臺(tái)。通過(guò)本文提供的方案,可以最小成本的實(shí)現(xiàn).NET?Framework應(yīng)用成功訪問(wèn)HTTP2站點(diǎn),感興趣的朋友跟隨小編一起看看吧2022-07-07Visual Studio中調(diào)試 .NET源代碼的實(shí)現(xiàn)步驟
在調(diào)試 .NET 應(yīng)用程序時(shí),有時(shí)你可能需要查看其他人的源代碼,本文主要介紹了Visual Studio中調(diào)試 .NET源代碼的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03.Net Core官方JWT授權(quán)驗(yàn)證的全過(guò)程
這篇文章主要給大家介紹了關(guān)于.Net Core官方JWT授權(quán)驗(yàn)證的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12ASP.NET將Session保存到數(shù)據(jù)庫(kù)中的方法
因?yàn)锳SP.NET中Session的存取機(jī)制與ASP相同,都是保存在進(jìn)行中, 一旦進(jìn)程崩潰,所有Session信息將會(huì)丟失,所以我采取了將Session信息保存到SQL Server中,盡管還有其它的2013-08-08Asp.net中使用DapperExtensions和反射來(lái)實(shí)現(xiàn)一個(gè)通用搜索
這篇文章主要介紹了Asp.net中使用DapperExtensions和反射來(lái)實(shí)現(xiàn)一個(gè)通用搜索功能,非常不錯(cuò),具有參考解決價(jià)值,需要的朋友可以參考下2017-03-03.NET+PostgreSQL實(shí)踐與避坑指南(推薦)
這篇文章主要介紹了.NET+PostgreSQL實(shí)踐與避坑指南,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01關(guān)于.net(C#)中的跨進(jìn)程訪問(wèn)的問(wèn)題
C# 跨進(jìn)程訪問(wèn)實(shí)現(xiàn)代碼。2009-04-04簡(jiǎn)單使用BackgroundWorker創(chuàng)建多個(gè)線程的教程
簡(jiǎn)單使用BackgroundWorker創(chuàng)建多個(gè)線程的教程,需要的朋友可以參考一下2013-03-03.net core使用redis基于StackExchange.Redis
這篇文章主要為大家詳細(xì)介紹了.net core使用redis基于StackExchange.Redis的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04