OpenHarmony NDK提供業(yè)界標(biāo)準(zhǔn)庫(kù) libc標(biāo)準(zhǔn)庫(kù)版述、 C++標(biāo)準(zhǔn)庫(kù) 澎灸,本文用于介紹C/C++標(biāo)準(zhǔn)庫(kù)在OpenHarmony中的機(jī)制炸宵,開發(fā)者了解這些機(jī)制有助于在NDK開發(fā)過(guò)程中避免相關(guān)問(wèn)題瓜客。
1. C++兼容性
在OpenHarmony系統(tǒng)中俭正,系統(tǒng)庫(kù)與應(yīng)用Native庫(kù)都在使用C++標(biāo)準(zhǔn)庫(kù)(參考 libc++版本 )奸鬓,系統(tǒng)庫(kù)依賴的C++標(biāo)準(zhǔn)庫(kù)隨鏡像版本升級(jí),而應(yīng)用Native庫(kù)依賴的C++標(biāo)準(zhǔn)庫(kù)隨編譯使用的SDK版本升級(jí)掸读,兩部分依賴的C++基礎(chǔ)庫(kù)會(huì)跨多個(gè)大版本串远,產(chǎn)生ABI兼容性問(wèn)題。為了解決此問(wèn)題儿惫,OpenHarmony上把兩部分依賴的C++標(biāo)準(zhǔn)庫(kù)進(jìn)行了區(qū)分澡罚。
- 系統(tǒng)庫(kù):使用libc++.so, 隨系統(tǒng)鏡像發(fā)布肾请。
- 應(yīng)用Native庫(kù):使用libc++_shared.so留搔,隨應(yīng)用發(fā)布。
兩個(gè)庫(kù)使用的C++命名空間不一樣铛铁,libc++.so使用__h作為C++符號(hào)的命名空間隔显,libc++_shared.so使用__n1作為C++符號(hào)的命名空間。
注意:系統(tǒng)和應(yīng)用使用的C++標(biāo)準(zhǔn)庫(kù)不能進(jìn)行混用避归,Native API接口當(dāng)前只能是C接口荣月,可以通過(guò)這個(gè)接口隔離兩邊的C++運(yùn)行環(huán)境。因此在使用共享庫(kù)HAR包構(gòu)建應(yīng)用時(shí)梳毙,如果HAR包含的libc++_shared.so不同于應(yīng)用使用的libc++_shared.so版本哺窄,那么只有其中一個(gè)版本會(huì)安裝到應(yīng)用里,可能會(huì)導(dǎo)致不兼容問(wèn)題,可以使用相同的SDK版本更新HAR包解決此問(wèn)題萌业。
已知C++兼容性問(wèn)題:應(yīng)用啟動(dòng)或者dlopen時(shí)hilog報(bào)錯(cuò)
symbol not found, s=__emutls_get_address
坷襟,原因是OpenHarmony 3.2及之前版本SDK中的libc++_shared.so無(wú)此符號(hào),而OpenHarmony4.0之后版本SDK的libc++_shared.so是有此符號(hào)的生年。解決此問(wèn)題需要更新應(yīng)用或者共享庫(kù)HAR包的SDK版本婴程。
2. musl libc動(dòng)態(tài)鏈接器
2.1 動(dòng)態(tài)庫(kù)加載命名空間隔離
動(dòng)態(tài)庫(kù)加載命名空間(namespace,下面統(tǒng)稱為ns)是動(dòng)態(tài)鏈接器設(shè)計(jì)的一個(gè)概念(區(qū)別于C++語(yǔ)言中的命名空間)抱婉,其設(shè)計(jì)的主要目的是為了在進(jìn)程中做native庫(kù)資源訪問(wèn)的管控档叔,以達(dá)到安全隔離的目的。例如系統(tǒng)native庫(kù)允許加載系統(tǒng)目錄(/system/lib64;/vendor/lib64等)下的native庫(kù)蒸绩,但是普通應(yīng)用native庫(kù)僅允許加載普通應(yīng)用native庫(kù)和ndk庫(kù)衙四,而不允許直接加載系統(tǒng)native庫(kù)。
動(dòng)態(tài)鏈接器無(wú)論是在加載編譯依賴(DT_NEEDED)中指定的共享庫(kù)患亿,還是調(diào)用dlopen
加載指定的共享庫(kù)传蹈,都需要關(guān)聯(lián)到具體的ns。
OpenHarmony中動(dòng)態(tài)庫(kù)加載namespace配置的情況
- default ns:動(dòng)態(tài)鏈接器啟動(dòng)時(shí)默認(rèn)創(chuàng)建的ns步藕,它可以搜索
/system/lib{abi};/vendor/lib{abi}
等系統(tǒng)目錄路徑下的so惦界。 - ndk ns:動(dòng)態(tài)鏈接器啟動(dòng)時(shí)默認(rèn)創(chuàng)建的ns,它可以搜索
/system/lib{abi}/ndk
目錄下的so咙冗,主要是暴露了NDK接口的so沾歪。 - app ns: 應(yīng)用啟動(dòng)時(shí)創(chuàng)建的ns,它的搜索路徑一般是應(yīng)用的安裝路徑(可能為沙箱路徑)乞娄,即可加載應(yīng)用的so瞬逊。
當(dāng)前這一套命名空間機(jī)制主要限制了應(yīng)用native庫(kù)和系統(tǒng)native庫(kù)之間的調(diào)用,如圖所示仪或,具體規(guī)則為
- default ns和ndk ns可以互相訪問(wèn)全部so确镊,不能訪問(wèn)app ns的so。
- app ns能訪問(wèn)ndk ns的全部so范删,不能訪問(wèn)default ns的so蕾域。
2.2 rpath機(jī)制
rpath(run-time path)是在運(yùn)行時(shí)指定共享庫(kù)搜索路徑的機(jī)制。該機(jī)制允許在可執(zhí)行文件或共享庫(kù)中嵌入一個(gè)用于在運(yùn)行時(shí)指定庫(kù)的搜索路徑的信息到旦。
由于上文介紹的命名空間隔離機(jī)制旨巷,應(yīng)用僅允許加載對(duì)應(yīng)安裝目錄拼接native庫(kù)路徑下(例如arm64平臺(tái)上為libs/arm64
)的應(yīng)用native庫(kù),當(dāng)應(yīng)用程序涉及加載較多的native庫(kù)添忘,期望創(chuàng)建多個(gè)native庫(kù)加載路徑方便管理采呐,但是會(huì)導(dǎo)致無(wú)法加載新創(chuàng)建目錄下的native庫(kù),這種情況可以通過(guò)rpath機(jī)制編譯時(shí)指定搜索路徑搁骑。
例如斧吐,應(yīng)用安裝目錄lib/arm64
下的libhello.so依賴新創(chuàng)建路徑lib/arm64/module
下的libworld.so又固,那么在應(yīng)用的CMakeList.txt里設(shè)置上rpath編譯選項(xiàng)后編譯,使用readelf
查看libhello.so的rpath配置如圖所示煤率,$ORIGIN
為libhello.so所在路徑仰冠,運(yùn)行時(shí)即可正常加載module目錄下的libworld.so。
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "\${ORIGIN}/module")
2.3 支持dlclose
支持使用dlclose真實(shí)卸載動(dòng)態(tài)庫(kù)的能力蝶糯。
2.4 支持symbol-version機(jī)制
symbol-version是libc在動(dòng)態(tài)鏈接-符號(hào)重定位階段的符號(hào)檢索機(jī)制洋只,支持不同版本的符號(hào)重定位,也可以幫助解決重復(fù)符號(hào)的問(wèn)題昼捍∈缎椋可參考 LD Version Scripts (GNU Gnulib)
寫在最后
- 如果你覺得這篇內(nèi)容對(duì)你還蠻有幫助,我想邀請(qǐng)你幫我三個(gè)小忙:
- 點(diǎn)贊妒茬,轉(zhuǎn)發(fā)舷礼,有你們的 『點(diǎn)贊和評(píng)論』,才是我創(chuàng)造的動(dòng)力郊闯。
- 關(guān)注小編,同時(shí)可以期待后續(xù)文章ing??蛛株,不定期分享原創(chuàng)知識(shí)团赁。
- 想要獲取更多完整鴻蒙最新學(xué)習(xí)知識(shí)點(diǎn),請(qǐng)移步前往小編:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu