一枫笛、介紹
????ARM:?
? ??是嵌入式中的一種架構(gòu),全稱為Advanced RISC Machine,可以理解為ARM處理器(也就是cpu)娇妓。? ? ?
? ? ABI(Application Binary Interface):
? ??應(yīng)用程序二進(jìn)制接口 描述了應(yīng)用程序和操作系統(tǒng)之間,一個(gè)應(yīng)用和它的庫之間活鹰,或者應(yīng)用的組成部分之間的低接口
? ? 通俗一點(diǎn)說就是: 不同android設(shè)備對應(yīng)的cpu指令集不同哈恰,架構(gòu)也不同,這樣當(dāng)我們需要使用cpu的時(shí)候就要尋找適合的指集志群、和架構(gòu).
? ??Android目前支持以下7種ABIs:? mips, mips64, X86, X86–64, arm64-v8a, armeabi, armeabi-v7a
? ? Android設(shè)備的ABI:
? ? 通常設(shè)備的ABI有兩種一種是主ABI,一種是輔ABI着绷。
? ? 在系統(tǒng)選擇ABI時(shí)會優(yōu)先選擇主ABI,如果不存在對應(yīng)的則會選擇輔的ABI:
? ??總的來說锌云,就是一個(gè)Android設(shè)備可以支持多種ABI,設(shè)備主ABI和輔助ABI,以arm64-v8a為主ABI的設(shè)備荠医,輔助ABI為armeabi-v7a和armeabi,以armeabi-v7a為主ABI的設(shè)備桑涎,輔助ABI為armeabi彬向。
? ? ABI的作用:
? ? ?我們在想使用c/c++的native庫的時(shí)候,需要提供不同的編譯包對應(yīng)不同的cpu架構(gòu)攻冷,也就是.so文件, 一般來說編譯包.so提供的是全套的cpu架構(gòu)娃胆,但是我們打包apk不需要全部都打包,因?yàn)檫@樣會很大程度增大apk體積等曼,所以ABI作用就在這里了里烦,只提供對應(yīng)的架構(gòu)的編譯包,也就是選擇最合適禁谦、最兼容招驴、性能最好的包,只需要在app下的build.gradle添加如下配置:
android{
? ? defaultConfig{
? ? ? ? ndk{? //指定 64位CPU使用32位so庫(其他類型如v8a枷畏、x86等會被過濾掉)
? ? ? ? ? ? abiFilters"armeabi-v7a"
? ? ? ? }
? ?}
}
二别厘、ABI與CPU關(guān)系
首先了解下不同ABI的簡介:
armeabi: 僅支持ARMv5架構(gòu)、僅支持軟浮點(diǎn)運(yùn)算拥诡,支持所有ARM*設(shè)備
armeabi-v7a: 支持ARMv7并向下兼容(輔ARMv5),支持硬浮點(diǎn)運(yùn)算,目前大部分機(jī)型都為v7a.
arm64-v8a: 支持ARMv8并向下兼容(輔ABI:ARMv5触趴、ARMv7), 同時(shí)包含32位(v7a)以及64位框架(v8a)
x86: 英特爾推出的32位框架 ,硬浮點(diǎn)運(yùn)算氮发,同時(shí)支持ARMv5架構(gòu)以及ARMv7(同為32位),不過在ARMv5中會有性能損耗.
x86_64:?英特爾推出的64位框架,向下兼容x86冗懦、ARMv5爽冕,通樣在性能上有所損耗
mips和mips_64:?MIPS是一種高性能的嵌入式CPU構(gòu)架,其出發(fā)點(diǎn)是高性能,主要用于路由器披蕉、貓等
可以看到不同CPU架構(gòu)對應(yīng)不同ABI支持情況
ARMv5 設(shè)備:只支持armeabi
ARMv7 設(shè)備:支持 armeabi 和 armeabi-v7a
ARMv8 設(shè)備:支持 armeabi-v7a颈畸、armeabi 和 arm64-v8a
X86 設(shè)備:支持 armeabi(性能有所損耗) 和 x86
x86_64 設(shè)備:支持 x86 和 x86_64
mips 設(shè)備: 支持 mips
mips_64 設(shè)備:支持 mips 和 mips_64
三、ABI適配
前面了解了不同設(shè)備的支持情況没讲,但是這些不同ABI是如何進(jìn)行加載的呢眯娱?
? ??ABI加載策略:
? ? 首先要明確,當(dāng)前設(shè)備支持的ABI架構(gòu)(主爬凑、輔架構(gòu))徙缴、以及當(dāng)前項(xiàng)目配置的ABI
? ? 其次再看我們的加載流程:
? ? 以ARMv8的cpu框架為例也就是支持v8a的設(shè)備為例:
?想要了解適配方案就要先了解軟浮點(diǎn)運(yùn)算(ARMv5)和硬浮點(diǎn)運(yùn)算(ARMv7以上)
軟浮點(diǎn)是通過浮點(diǎn)庫去實(shí)現(xiàn)浮點(diǎn)運(yùn)算的,效率低嘁信;硬浮點(diǎn)是通過浮點(diǎn)運(yùn)算單元(FPU)來完成的于样,效率高。
????(1)硬浮點(diǎn)(hard-float)
編譯器將代碼直接編譯成硬件浮點(diǎn)協(xié)處理器(浮點(diǎn)運(yùn)算單元FPU)能識別的指令潘靖,這些指令在執(zhí)行的時(shí)候ARM核直接把它轉(zhuǎn)給協(xié)處理器執(zhí)行穿剖。FPU 通常有一套額外的寄存器來完成浮點(diǎn)參數(shù)傳遞和運(yùn)算。使用實(shí)際的硬件浮點(diǎn)運(yùn)算單元(FPU)會帶來性能的提升卦溢。
????(2)軟浮點(diǎn)(soft-float)
編譯器把浮點(diǎn)運(yùn)算轉(zhuǎn)成浮點(diǎn)運(yùn)算的函數(shù)調(diào)用和庫函數(shù)調(diào)用携御,沒有FPU的指令調(diào)用,也沒有浮點(diǎn)寄存器的參數(shù)傳遞既绕。浮點(diǎn)參數(shù)的傳遞也是通過ARM寄存器或者堆棧完成∽纳玻現(xiàn)在的Linux系統(tǒng)默認(rèn)編譯選擇使用hard-float,如果系統(tǒng)沒有任何浮點(diǎn)處理器單元,這就會產(chǎn)生非法指令和異常凄贩。因而一般的系統(tǒng)鏡像都采用軟浮點(diǎn)以兼容沒有VFP的處理器誓军。
了解了.so的加載策略,下面說下具體如何去適配.
? ? 適配方案:
? ? 1. 適配armeabi-v7a疲扎,市場上主流機(jī)型昵时,可兼容大部分設(shè)備除非過老機(jī)型,android2.2以下版本一般會采用老的CPU架構(gòu)椒丧,
這種適配方式壹甥,除去ARMv5架構(gòu)的機(jī)型都可以適配.
? ? 2. 適配armeabi, 這種適配方式會兼容所有類型的CPU壶熏,但是需要注意的是如果你的.SO包含使用CPU核心或者說對CPU使用過大的話句柠,不建議此種方式, 原因就是:目前主流為ARM7,上面也說了ARMv5架構(gòu)為軟浮點(diǎn)運(yùn)算,而這種低效率算法在CPU使用上效率不如硬浮點(diǎn)算法溯职,也就是ARMv7對應(yīng)armeabi-v7a類型ABI精盅。
? ? 3. 適配arm-v8a, 這種方式適配了ARMv8(64位)的機(jī)型,也就是說這種機(jī)型會向下兼容ARMv7(32位)以及ARMv5架構(gòu)谜酒,但是忽略了部分使用ARMv7的機(jī)型叹俏。
? ? 目前的主流配置基本就這3中,你也可以同時(shí)適配多種僻族,但是會增大apk體積, 還有一類問題就是第三方的庫只支持armeabi粘驰,而我們的項(xiàng)目需要v7a這類去適配,這樣2個(gè)庫沒有交集述么,我們該如何去選擇適配蝌数?
? ??第三方適配方案:
? ? 1. 首先要確定一個(gè)問題, 你在使用CPU中哪個(gè)庫對CPU的使用需求量更大或者更主要碉输,由于兩種庫沖突,我們必須合并適配亭珍,我們模擬v7a的這類庫對CPU需求更大敷钾,那我們可以這樣: 保留armeabi-v7a的庫,將第三方的armeabi中的.so放入v7a中肄梨,這樣我們統(tǒng)一了適配方案阻荒,前提是第三方庫支持這樣做.
? ? 2. 那如果第三方不支持這樣,那我們需要用到另一個(gè)方案 : 將v7a庫中的.so放入第三方的armeabi中, 這樣也是將v7a合并到了armeabi中众羡,但是由于咱們v7a對CPU需求大侨赡,不排除這樣配置會導(dǎo)致cpu使用效率下降.
以上就是關(guān)于ABI適配的一些方案和問題有錯(cuò)誤之處還望指教!
四、市場占有度
知道了適配方案粱侣,我們更要了解下市場上各個(gè)CPU類型的占有率羊壹,更容易讓我們確定我們適配的方向:
ARMv5 設(shè)備:目前幾乎遇不到這類機(jī)型,不排除特殊機(jī)型
ARMv7 設(shè)備:支持 armeabi 和 armeabi-v7a, 目前來說也是相對比較老的機(jī)型齐婴,一般是android 7.0以下的設(shè)備油猫。
ARMv8 設(shè)備:支持 armeabi-v7a、armeabi 和 arm64-v8a柠偶,目前主流的類型情妖,基本上主流機(jī)型,android10左右都是使用這類架構(gòu)诱担。
X86 設(shè)備:支持 armeabi(性能有所損耗) 和 x86
x86_64 設(shè)備:支持 x86 和 x86_64
mips 設(shè)備: 支持 mips
mips_64 設(shè)備:支持 mips 和 mips_64