Google is committed to advancing racial equity for Black communities. See how.
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

鏈接器命名空間

動態鏈接器解決了Treble VNDK設計中的兩個挑戰:

  • SP-HAL共享庫及其依賴項(包括VNDK-SP庫)已加載到框架進程中。應該有一些防止符號衝突的機制。
  • dlopen()android_dlopen_ext()可能會引入一些運行時依賴項,這些依賴項在構建時不可見,並且使用靜態分析可能很難檢測到。

這兩個挑戰可以通過鏈接器名稱空間機制解決。該機制由動態鏈接器提供。它可以將共享庫隔離在不同的鏈接器命名空間中,以使具有相同庫名但具有不同符號的庫不會衝突。

另一方面,鏈接程序名稱空間機制提供了靈活性,因此某些共享庫可以由鏈接程序名稱空間導出並由另一個鏈接程序名稱空間使用。這些導出的共享庫可以成為其他程序公共的應用程序編程接口,同時將其實現細節隱藏在其鏈接器名稱空間中。

例如,/ /system/lib[64]/libcutils.so / /system/lib[64]/vndk-sp-${VER}/libcutils.so /system/lib[64]/libcutils.so/system/lib[64]/vndk-sp-${VER}/libcutils.so是兩個共享庫。這兩個庫可以具有不同的符號。它們被加載到不同的鏈接器命名空間中,以便框架模塊可以依賴於/system/lib[64]/libcutils.so而SP-HAL共享庫可以依賴於/system/lib[64]/vndk-sp-${VER}/libcutils.so

另一方面,/ /system/lib[64]/libc.so是一個公共庫的示例,該公共庫由鏈接器名稱空間導出並導入到許多鏈接器名稱空間中。 /system/lib[64]/libc.so的依賴/system/lib[64]/libc.so (如libnetd_client.so )被加載到/system/lib[64]/libc.so所在的名稱空間中。其他名稱空間將無法訪問這些依賴項。該機制在提供公共接口的同時封裝了實現細節。

它是如何工作的?

動態鏈接程序負責加載DT_NEEDED條目中指定的共享庫或dlopen()android_dlopen_ext()的參數指定的共享庫。在這兩種情況下,動態鏈接程序都會找到調用程序所在的鏈接程序名稱空間,並嘗試將依賴項加載到同一鏈接程序名稱空間中。如果動態鏈接器無法將共享庫加載到指定的鏈接器名稱空間中,它將向鏈接的鏈接器名稱空間詢問導出的共享庫。

配置文件格式

配置文件格式基於INI文件格式。典型的配置文件如下所示:

dir.system = /system/bin
dir.system = /system/xbin
dir.vendor = /vendor/bin

[system]
additional.namespaces = sphal,vndk

namespace.default.isolated = true
namespace.default.search.paths = /system/${LIB}
namespace.default.permitted.paths = /system/${LIB}/hw
namespace.default.asan.search.paths = /data/asan/system/${LIB}:/system/${LIB}
namespace.default.asan.permitted.paths = /data/asan/system/${LIB}/hw:/system/${LIB}/hw

namespace.sphal.isolated = true
namespace.sphal.visible = true
namespace.sphal.search.paths = /odm/${LIB}:/vendor/${LIB}
namespace.sphal.permitted.paths = /odm/${LIB}:/vendor/${LIB}
namespace.sphal.asan.search.paths  = /data/asan/odm/${LIB}:/odm/${LIB}
namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}:/vendor/${LIB}
namespace.sphal.asan.permitted.paths  = /data/asan/odm/${LIB}:/odm/${LIB}
namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}:/vendor/${LIB}
namespace.sphal.links = default,vndk
namespace.sphal.link.default.shared_libs = libc.so:libm.so
namespace.sphal.link.vndk.shared_libs = libbase.so:libcutils.so

namespace.vndk.isolated = true
namespace.vndk.search.paths = /system/${LIB}/vndk-sp-29
namespace.vndk.permitted.paths = /system/${LIB}/vndk-sp-29
namespace.vndk.links = default
namespace.vndk.link.default.shared_libs = libc.so:libm.so

[vendor]
namespace.default.isolated = false
namespace.default.search.paths = /vendor/${LIB}:/system/${LIB}

配置文件包括:

  • 動態鏈接程序開始時有幾個目錄節映射屬性,用於選擇有效節。
  • 幾個鏈接器名稱空間配置部分:
    • 每個部分都包含多個命名空間(圖形頂點)和命名空間之間的多個後備鏈接(圖形弧)。
    • 每個名稱空間都有其自己的隔離,搜索路徑,允許的路徑和可見性設置。

下表詳細描述了每個屬性的含義。

目錄部分映射屬性

屬性描述

dir. name

[ name ]部分適用的目錄的路徑。

每個屬性將目錄下的可執行文件映射到鏈接器名稱空間配置部分。可能有兩個(或多個)具有相同name但指向不同目錄的屬性。

dir.system = /system/bin
dir.system = /system/xbin
dir.vendor = /vendor/bin

這表明[system]部分中指定的配置適用於從/system/bin/system/xbin加載的可執行文件。

[vendor]部分中指定的配置適用於從/vendor/bin加載的可執行文件。

關係屬性

屬性描述
additional. namespaces

這部分的逗號分隔的其他名稱空間列表(除了default名稱空間)。

additional. namespaces = sphal, vndk

這表示[system]配置中有三個名稱空間( defaultsphalvndk )。

namespace. name . links

後備名稱空間的逗號分隔列表。

如果在當前名稱空間中找不到共享庫,則動態鏈接程序將嘗試從後備名稱空間中加載共享庫。在列表開頭指定的名稱空間具有更高的優先級。

namespace. sphal. links = default, vndk

如果共享庫或可執行文件請求無法加載到sphal名稱空間的共享庫,則動態鏈接程序將嘗試從default名稱空間加載共享庫。

然後,如果也不能從default名稱空間中加載共享庫,則動態鏈接程序將嘗試從vndk名稱空間中加載共享庫。

最後,如果所有嘗試均失敗,則動態鏈接器將返回錯誤。

namespace. name . link. other . shared_libs

如果在name命名空間中找不到共享庫,可以在other命名空間中搜索這些共享庫的冒號分隔列表。

此屬性不能與namespace. name . link. other . allow_all_shared_libs一起使用namespace. name . link. other . allow_all_shared_libs

namespace. sphal. link. default. shared_libs = libc.so: libm.so

這表明後備鏈接僅接受libc.solibm.so作為請求的庫名。如果請求的庫名稱不是libc.solibm.so ,則動態鏈接程序將忽略從sphaldefault名稱空間的回退鏈接。

namespace. name . link. other . allow_all_shared_libs

一個布爾值,指示當在name命名空間中找不到共享庫時是否可以在other命名空間中搜索所有共享庫。

此屬性不能與namespace. name . link. other . shared_libs一起使用namespace. name . link. other . shared_libs

namespace. vndk. link. sphal. allow_all_shared_libs = true

這表明所有庫名稱都可以遍歷從vndksphal名稱空間的後備鏈接。

命名空間屬性

屬性描述
namespace. name . isolated

一個布爾值,指示動態鏈接器是否應檢查共享庫所在的位置。

如果isolatedtrue ,僅顯示一個共享庫search.paths目錄(不包括子目錄)或是一個 permitted.paths目錄(包括子目錄)可以被加載。

如果isolatedfalse (默認),則動態鏈接程序將不檢查共享庫的路徑。

namespace. sphal. isolated = true

這表明僅在共享庫search.paths或下permitted.paths可以被加載到sphal命名空間。

namespace. name . search.paths

用冒號分隔的目錄列表以搜索共享庫。

如果對dlopen()DT_NEEDED條目的函數調用未指定完整路徑,則search.paths中指定的目錄將位於請求的庫名之前。列表開頭指定的目錄具有更高的優先級。

isolatedtrue之一,共享庫search.paths目錄(不包括子目錄)可以不管的加載permitted.paths屬性。

例如,如果search.paths/system/${LIB}permitted.paths是空的, /system/${LIB}/libc.so可以加載但/system/${LIB}/vndk/libutils.so無法加載。

namespace. default. search.paths = /system/${LIB}

這表明動態鏈接器在/system/${LIB}搜索共享庫。

namespace. name . asan.search.paths

啟用AddressSanitizer(ASan)後,用冒號分隔的目錄列表以搜索共享庫。

namespace. name . search.paths啟用ASan時將忽略namespace. name . search.paths

namespace. default. asan.search.paths = /data/asan/system/${LIB}: /system/${LIB}

這表示在啟用ASan時,動態鏈接程序首先搜索/data/asan/system/${LIB} ,然後搜索/system/${LIB}

namespace. name . permitted.paths

目錄的冒號分隔的列表(包括子目錄),動態連接器可以加載共享庫(除了search.paths時) isolatedtrue

是的子目錄下的共享庫permitted.paths也可裝載。例如,如果permitted.paths/system/${LIB}/system/${LIB}/libc.so/system/${LIB}/vndk/libutils.so可以加載。

如果isolatedfalse ,則permitted.paths將被忽略並發出警告。

namespace. default. permitted.paths = /system/${LIB}/hw

這表明可以將/system/${LIB}/hw下的共享庫加載到隔離的default名稱空間中。

例如,如果沒有permitted.pathslibaudiohal.so無法加載/system/${LIB}/hw/audio.a2dp.default.sodefault命名空間。

namespace. name . asan.permitted.paths

啟用ASan時,動態鏈接程序可以在其中裝載共享庫的目錄的冒號分隔列表。

namespace. name . permitted.paths時,忽略牙山啟用。

namespace. default. asan.permitted.paths = /data/asan/system/${LIB}/hw: /system/${LIB}/hw

這表示啟用ASan時, 可以/data/asan/system/${LIB}/hw/system/${LIB}/hw下的共享庫加載到隔離的default名稱空間中。

namespace. name . visible

一個布爾值,指示程序(除libc )是否可以使用android_get_exported_namespace()獲取鏈接器名稱空間句柄,並通過將句柄傳遞給android_dlopen_ext()來在鏈接器名稱空間中打開共享庫。

如果visibletrue ,則android_get_exported_namespace()始終返回名稱空間存在的句柄。

如果visiblefalse (默認值),則android_get_exported_namespace()始終返回NULL無論名稱空間是否存在。共享庫只能在以下情況下加載到此命名空間中:(1)具有鏈接到該命名空間的備用鏈接器命名空間請求它們,或者(2)此命名空間中的其他共享庫或可執行文件請求它們。

namespace. sphal. visible = true

這表示android_get_exported_namespace("sphal")可以返回有效的鏈接器名稱空間句柄。

鏈接器名稱空間的創建

在Android 11中,鏈接器配置是在運行時在/linkerconfig下創建的,而不是使用${android-src}/system/core/rootdir/etc純文本文件。該配置是在啟動時根據運行時環境生成的,其中包括以下各項:

  • 如果設備支持VNDK
  • 供應商分區的目標VNDK版本
  • 產品分區的VNDK版本
  • 已安裝的APEX模塊

鏈接器配置是通過解決鏈接器名稱空間之間的依賴關係而創建的。例如,如果APEX模塊上有任何包含依賴項更新的更新,則會生成反映這些更改的鏈接器配置。在${android-src}/system/linkerconfig可以找到創建鏈接器配置的更多詳細信息。

鏈接器名稱空間隔離

共有三種配置類型。取決於的值PRODUCT_TREBLE_LINKER_NAMESPACESBOARD_VNDK_VERSIONBoardConfig.mk ,在啟動時產生的對應配置。

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
所選配置 VTS要求
true current VNDK 對於使用Android 9或更高版本啟動的設備必選
空的 VNDK Lite 對於使用Android 8.x發行的設備必須提供
false 空的 Legacy 對於非高音設備

VNDK Lite配置隔離了SP-HAL和VNDK-SP共享庫。在Android 8.0中,當PRODUCT_TREBLE_LINKER_NAMESPACEStrue時,這必須是動態鏈接器的配置文件。

VNDK配置還隔離了SP-HAL和VNDK-SP共享庫。此外,此配置提供了完整的動態鏈接器隔離。這樣可以確保系統分區中的模塊不會依賴於供應商分區中的共享庫,反之亦然。

在Android 8.1或更高版本中,VNDK配置是默認配置,強烈建議通過將BOARD_VNDK_VERSION設置為current來啟用完全動態鏈接程序隔離。

VNDK配置

VNDK配置隔離了系統分區和供應商分區之間的共享庫依賴關係。與前面小節中提到的配置相比,差異概述如下:

  • 框架流程

    • 將創建defaultvndksphalrs命名空間。
    • 所有名稱空間都是隔離的。
    • 系統共享庫被加載到default名稱空間中。
    • SP-HAL被加載到sphal名稱空間中。
    • VNDK-SP共享庫已加載到vndk命名空間中。
  • 供應商流程

    • 將創建defaultvndksystem名稱空間。
    • default名稱空間是隔離的。
    • 供應商共享庫被加載到default名稱空間中。
    • VNDK和VNDK-SP共享庫已加載到vndk命名空間中。
    • LL-NDK及其依賴項被加載到system名稱空間中。

鏈接器名稱空間之間的關係如下所示。

VNDK配置中描述的鏈接器名稱空間圖
圖1.鏈接器名稱空間隔離(VNDK配置)

在上圖中, LL-NDKVNDK-SP代表以下共享庫:

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libGLESv3.so
    • libandroid_net.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libneuralnetworks.so
    • libsync.so
    • libvndksupport.so
    • libvulkan.so
  • VNDK-SP
    • android.hardware.graphics.common@1.0.so
    • android.hardware.graphics.mapper@2.0.so
    • android.hardware.renderscript@1.0.so
    • android.hidl.memory@1.0.so
    • libRSCpuRef.so
    • libRSDriver.so
    • libRS_internal.so
    • libbase.so
    • libbcinfo.so
    • libc++.so
    • libcutils.so
    • libhardware.so
    • libhidlbase.so
    • libhidlmemory.so
    • libhidltransport.so
    • libhwbinder.so
    • libion.so
    • libutils.so
    • libz.so

您可以從設備的/linkerconfig/ld.config.txt找到更多詳細信息。

VNDK Lite配置

從Android 8.0開始,動態鏈接器已配置為隔離SP-HAL和VNDK-SP共享庫,以使它們的符號不會與其他框架共享庫衝突。鏈接器名稱空間之間的關係如下所示。

VNDK Lite配置中描述的鏈接器名稱空間圖
圖2.鏈接器名稱空間隔離(VNDK Lite配置)

LL-NDKVNDK-SP代表以下共享庫:

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libstdc++.so (不在配置中)
    • libsync.so
    • libvndksupport.so
    • libz.so (在配置中移至VNDK-SP
  • VNDK-SP
    • android.hardware.graphics.common@1.0.so
    • android.hardware.graphics.mapper@2.0.so
    • android.hardware.renderscript@1.0.so
    • android.hidl.memory@1.0.so
    • libbase.so
    • libc++.so
    • libcutils.so
    • libhardware.so
    • libhidlbase.so
    • libhidlmemory.so
    • libhidltransport.so
    • libhwbinder.so
    • libion.so
    • libutils.so

下表列出了框架過程的名稱空間配置,該配置摘錄自VNDK Lite配置的[system]部分。

命名空間屬性
default search.paths /system/${LIB}
/odm/${LIB}
/vendor/${LIB}
/product/${LIB}
isolated false
sphal search.paths /odm/${LIB}
/vendor/${LIB}
permitted.paths /odm/${LIB}
/vendor/${LIB}
isolated true
visible true
links default,vndk,rs
link.default.shared_libs LL-NDK
link.vndk.shared_libs VNDK-SP
link.rs.shared_libs libRS_internal.so
vndk (用於VNDK-SP) search.paths /odm/${LIB}/vndk-sp
/vendor/${LIB}/vndk-sp
/system/${LIB}/vndk-sp-${VER}
permitted.paths /odm/${LIB}/hw
/odm/${LIB}/egl
/vendor/${LIB}/hw
/vendor/${LIB}/egl
/system/${LIB}/vndk-sp-${VER}/hw
isolated true
visible true
links default
link.default.shared_libs LL-NDK
rs (用於RenderScript) search.paths /odm/${LIB}/vndk-sp
/vendor/${LIB}/vndk-sp
/system/${LIB}/vndk-sp-${VER}
/odm/${LIB}
/vendor/${LIB}
permitted.paths /odm/${LIB}
/vendor/${LIB}
/data (用於已編譯的RS內核)
isolated true
visible true
links default,vndk
link.default.shared_libs LL-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

下表顯示了供應商流程的名稱空間配置,該配置摘錄自VNDK Lite配置中的[vendor]部分。

命名空間屬性
default search.paths /odm/${LIB}
/odm/${LIB}/vndk
/odm/${LIB}/vndk-sp
/vendor/${LIB}
/vendor/${LIB}/vndk
/vendor/${LIB}/vndk-sp
/system/${LIB}/vndk-${VER}
/system/${LIB}/vndk-sp-${VER}
/system/${LIB} (已棄用)
/product/${LIB} (已棄用)
isolated false

可以從設備的/linkerconfig/ld.config.txt找到更多詳細信息。

文件紀錄

Android 11的變化

  • 在Android 11中,靜態ld.config.*.txt文件已從代碼庫中刪除,而LinkerConfig會在運行時生成它們。

Android 9變更

  • 在Android 9中,將vndk鏈接器名稱空間添加到供應商進程,並且VNDK共享庫與默認鏈接器名稱空間隔離。
  • PRODUCT_FULL_TREBLE替換為更具體的PRODUCT_TREBLE_LINKER_NAMESPACES
  • Android 9更改以下動態鏈接器配置文件的名稱。
    Android 8.x Android 9 描述
    ld.config.txt.in ld.config.txt 對於具有運行時鏈接程序名稱空間隔離的設備
    ld.config.txt ld.config.vndk_lite.txt 對於具有VNDK-SP鏈接器名稱空間隔離的設備
    ld.config.legacy.txt ld.config.legacy.txt 對於運行Android 7.x或更低版本的舊設備
  • 刪除android.hardware.graphics.allocator@2.0.so
  • productodm分區已添加。