APP開發實戰170-ABI管理和SO文件的使用簡介

23ABI管理

23.1 ABI簡介

不同Android設備使用不同的CPU,因此支持不同的指令集。CPU與指令集的每種組合都有其自己的應用二進制界面(或 ABI)。 ABI可以非常精確地定義應用的機器代碼在運行時如何與系統交互。開發者必須爲應用要使用的每個 CPU架構指定ABI。                                                      

典型的ABI 包含以下信息:

機器代碼應使用的 CPU 指令集。

運行時內存存儲和加載的字節順序。

可執行二進制文件(例如程序和共享庫)的格式,以及它們支持的內容類型。

用於解析內容與系統之間數據的各種約定。這些約定包括對齊限制,以及系統如何使用堆棧和在調用函數時註冊。

運行時可用於機器代碼的函數符號列表 - 通常來自非常具體的庫集。

(Android系統採用小字節序 ARM GNU/Linux ABI)

23.2 支持的ABI

每個 ABI 支持一個或多個指令集,下表是每個 ABI 支持的指令集概:

ABI

支持的指令集

說明

armeabi

ARMV5TE 和更高版本

  Thumb-1

無硬浮點。

armeabi-v7a

  armeabi

  Thumb-2

  VFPv3-D16

  其他(可選)

與 ARMv5、v6 設備不兼容。

arm64-v8a

  AArch-64

x86

  x86 (IA-32)

  MMX

  SSE/2/3

  SSSE3

不支持 MOVBE 或 SSE4。

x86_64

  x86-64

  MMX

  SSE/2/3

  SSSE3

  SSE4.1、4.2

  POPCNT

mips

MIPS32r1 及更高版本

使用硬浮點

mips64

  MIPS64r6

(1)armeabi

此 ABI 適用於基於 ARM、至少支持 ARMv5TE 指令集的 CPU,不支持硬件輔助的浮點計算。相反,所有浮點運算都使用編譯器 libgcc.a 靜態庫中的軟件幫助程序函數。

此ABI 支持 ARM 的 Thumb(亦稱 Thumb-1)指令集。NDK 默認生成 Thumb 代碼,除非在 Android.mk 文件中使用 LOCAL_ARM_MODE 變量指定不同的行爲。

 

(2)armeabi-v7a

此ABI可擴展 armeabi 以包含多個 CPU 指令集擴展,包括:

Thumb-2 指令集擴展,其性能堪比 32 位 ARM 指令,簡潔性類似於 Thumb-1。

VFP 硬件 FPU 指令。更具體一點,包括 VFPv3-D16,它除了 ARM 核心中的 16 個 32 位寄存器之外,還包含 16 個專用 64 位浮點寄存器。

v7-a ARM 規格描述的其他擴展,包括 高級 SIMD(亦稱 NEON)、VFPv3-D32 和 ThumbEE,都是此 ABI 可選的。

 

(3)arm64-v8a

此 ABI 適用於基於 ARMv8、支持 AArch64 的 CPU。它還包含 NEON 和 VFPv4 指令集。

(4)x86

此ABI 適用於支持通常稱爲“x86”或“IA-32”的指令集的 CPU。

 

(5)x86_64

此ABI 適用於支持通常稱爲“x86-64”的指令集的 CPU。

 

(6)mips

此ABI 適用於基於 MIPS、至少支持 MIPS32r1指令集的 CPU。

 

(7)mips64

此ABI 適用於 MIPS64 R6。

23.3 爲特定ABI生成代碼

默認情況下,NDK 爲 armeabi ABI生成機器代碼。但可以通過向 Application.mk文件添加以下行生成 ARMv7-a 兼容的機器代碼:

APP_ABI := armeabi-v7a

要爲兩個或更多不同的 ABI 構建機器代碼,請使用空格作爲分隔符。例如:

APP_ABI := armeabi armeabi-v7a

此設置指示 NDK 爲機器代碼構建兩個版本:此行中所列的每個 ABI 一個。

構建多個機器代碼版本時,構建系統會將庫複製到應用項目路徑,並最終將它們封裝到 APK 中,從而創建一個胖二進制文件。 胖二進制文件大於只包含一個系統的機器代碼的二進制文件;權衡方式是兼容性更廣,但 APK 更大。

在安裝時,軟件包管理器只解包最適合目標設備的機器代碼。

23.4 Android平臺上的ABI管理

Android的軟件包管理器預期在 APK中符合以下模式的文件路徑上查找 NDK 生成的庫:

/lib/<abi>/lib<name>.so

這裏的 <abi> 是支持的ABI 下面列出的 ABI 名稱之一,<name> 是爲 Android.mk文件中的 LOCAL_MODULE 變量定義庫時使用的庫名稱。 由於 APK文件只是 zip 文件,因此打開它們並確認它們屬於哪些共享原生庫很簡單。

如果系統在預期位置找不到原生共享庫,便無法使用它們。 在這種情況下,應用本身必須複製這些庫,然後執行 dlopen()。

在胖二進制文件中,每個庫位於其名稱與相應 ABI 匹配的目錄下。例如,胖二進制文件可能包含:

/lib/armeabi/libfoo.so

/lib/armeabi-v7a/libfoo.so

/lib/arm64-v8a/libfoo.so

/lib/x86/libfoo.so

/lib/x86_64/libfoo.so

/lib/mips/libfoo.so

/lib/mips64/libfoo.so

23.5 Android平臺ABI支持

Android 系統在運行時知道它支持哪些 ABI,因爲版本特定的系統屬性會指示:

設備的主要ABI,與系統映像本身使用的機器代碼對應。

可選的輔助ABI,與系統映像也支持的另一個ABI 對應。

此機制確保系統在安裝時從軟件包提取最佳機器代碼。

爲實現最佳性能,應直接針對主要 ABI 進行編譯。例如,基於 ARMv5TE 的典型設備只會定義主要 ABI:armeabi。相反,基於 ARMv7 的典型設備將主要ABI定義爲 armeabi-v7a,而將輔助ABI定義爲 armeabi,因爲它可以運行爲每個 ABI 生成的應用原生二進制文件。

許多基於 x86 的設備也可運行 armeabi-v7a 和 armeabi NDK 二進制文件。對於這些設備,主要 ABI將是 x86,輔助ABI是 armeabi-v7a。

基於 MIPS 的典型設備只定義主要 ABI:mips。

23.6 安裝時自動解壓縮原生代碼

安裝應用時,軟件包管理器服務將掃描 APK,查找以下形式的任何共享庫:

lib/<primary-abi>/lib<name>.so

如果未找到,並且已定義輔助 ABI,該服務將掃描以下形式的共享庫:

lib/<secondary-abi>/lib<name>.so

找到所需的庫時,軟件包管理器會將它們複製到應用的 data 目錄 (data/data/<package_name>/lib/)下的 /lib/lib<name>.so。

如果根本沒有共享對象文件,應用也會構建並安裝,但在運行時會崩潰。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章