Không gian tên của trình liên kết

Trình liên kết động giải quyết hai thách thức trong thiết kế Treble VNDK:

  • Thư viện dùng chung SP-HAL và các phần phụ thuộc của thư viện này, bao gồm cả thư viện VNDK-SP, được tải vào các quy trình khung. Cần có một số cơ chế để ngăn xung đột biểu tượng.
  • dlopen()android_dlopen_ext() có thể đưa ra một số phần phụ thuộc thời gian chạy không hiển thị tại thời điểm tạo bản dựng và có thể khó phát hiện bằng cách sử dụng tính năng phân tích tĩnh.

Hai thách thức này có thể được giải quyết bằng cơ chế không gian tên trình liên kết. Cơ chế này do trình liên kết động cung cấp. Tệp này có thể tách riêng các thư viện dùng chung trong nhiều không gian tên trình liên kết để các thư viện có cùng tên thư viện nhưng có ký hiệu khác nhau sẽ không xung đột với nhau.

Mặt khác, cơ chế không gian tên trình liên kết mang lại sự linh hoạt để một số thư viện dùng chung có thể được xuất bằng một không gian tên trình liên kết và được một không gian tên trình liên kết khác sử dụng. Các thư viện dùng chung đã xuất này có thể trở thành giao diện lập trình ứng dụng công khai với các chương trình khác, đồng thời ẩn thông tin triển khai của các thư viện đó trong không gian tên của trình liên kết.

Ví dụ: /system/lib[64]/libcutils.so/system/lib[64]/vndk-sp-${VER}/libcutils.so là hai thư viện dùng chung. Hai thư viện này có thể có các ký hiệu khác nhau. Các mô-đun này được tải vào nhiều không gian tên của trình liên kết để các mô-đun khung có thể phụ thuộc vào /system/lib[64]/libcutils.so và thư viện chia sẻ SP-HAL có thể phụ thuộc vào /system/lib[64]/vndk-sp-${VER}/libcutils.so.

Mặt khác, /system/lib[64]/libc.so là ví dụ về một thư viện công khai do không gian tên trình liên kết xuất và nhập vào nhiều không gian tên trình liên kết. Các phần phụ thuộc của /system/lib[64]/libc.so, chẳng hạn như libnetd_client.so, sẽ được tải vào không gian tên mà /system/lib[64]/libc.so nằm trong đó. Các không gian tên khác sẽ không có quyền truy cập vào các phần phụ thuộc đó. Cơ chế này đóng gói thông tin triển khai chi tiết trong khi vẫn cung cấp giao diện công khai.

Cách hoạt động

Trình liên kết động chịu trách nhiệm tải các thư viện dùng chung được chỉ định trong mục DT_NEEDED hoặc các thư viện dùng chung được chỉ định bằng đối số của dlopen() hoặc android_dlopen_ext(). Trong cả hai trường hợp, trình liên kết động sẽ tìm không gian tên của trình liên kết nơi lệnh gọi nằm và cố gắng tải các phần phụ thuộc vào cùng một không gian tên của trình liên kết. Nếu trình liên kết động không thể tải thư viện dùng chung vào không gian tên trình liên kết đã chỉ định, thì trình liên kết này sẽ yêu cầu không gian tên trình liên kết được liên kết cung cấp các thư viện dùng chung đã xuất.

Định dạng tệp cấu hình

Định dạng tệp cấu hình dựa trên định dạng tệp INI. Tệp cấu hình thông thường sẽ có dạng như sau:

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}

Tệp cấu hình bao gồm:

  • Một số thuộc tính ánh xạ thư mục-phần ở đầu để trình liên kết động chọn phần hiệu quả.
  • Một số phần cấu hình không gian tên trình liên kết:
    • Mỗi phần chứa một số không gian tên (đỉnh đồ thị) và một số đường liên kết dự phòng giữa các không gian tên (cung đồ thị).
    • Mỗi không gian tên có các chế độ cài đặt tách biệt, đường dẫn tìm kiếm, đường dẫn được phép và chế độ cài đặt chế độ hiển thị riêng.

Các bảng dưới đây mô tả chi tiết ý nghĩa của từng thuộc tính.

Thuộc tính liên kết thư mục-mục

Thuộc tính Mô tả Ví dụ

dir.name

Đường dẫn đến thư mục mà phần [name] áp dụng.

Mỗi thuộc tính liên kết các tệp thực thi trong thư mục với một phần cấu hình không gian tên của trình liên kết. Có thể có hai (hoặc nhiều) thuộc tính có cùng name nhưng trỏ đến các thư mục khác nhau.

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

Điều này cho biết cấu hình được chỉ định trong phần [system] áp dụng cho các tệp thực thi được tải từ /system/bin hoặc /system/xbin.

Cấu hình được chỉ định trong phần [vendor] áp dụng cho các tệp thực thi được tải từ /vendor/bin.

Thuộc tính quan hệ

Thuộc tính Mô tả Ví dụ
additional.namespaces

Danh sách các không gian tên bổ sung (ngoài không gian tên default) được phân tách bằng dấu phẩy cho phần này.

additional.namespaces = sphal,vndk

Điều này cho biết có ba không gian tên (default, sphalvndk) trong cấu hình [system].

namespace.name.links

Danh sách không gian tên dự phòng được phân tách bằng dấu phẩy.

Nếu không tìm thấy thư viện dùng chung trong không gian tên hiện tại, trình liên kết động sẽ cố gắng tải thư viện dùng chung từ các không gian tên dự phòng. Không gian tên được chỉ định ở đầu danh sách có mức độ ưu tiên cao hơn.

namespace.sphal.links = default,vndk

Nếu một thư viện dùng chung hoặc một tệp thực thi yêu cầu một thư viện dùng chung không thể tải vào không gian tên sphal, thì trình liên kết động sẽ cố gắng tải thư viện dùng chung từ không gian tên default.

Sau đó, nếu không thể tải thư viện dùng chung từ không gian tên default, trình liên kết động sẽ cố gắng tải thư viện dùng chung từ không gian tên vndk.

Cuối cùng, nếu tất cả các lần thử đều không thành công, trình liên kết động sẽ trả về lỗi.

namespace.name.link.other.shared_libs

Một danh sách các thư viện dùng chung được phân tách bằng dấu hai chấm mà bạn có thể tìm kiếm trong không gian tên other khi không tìm thấy các thư viện đó trong không gian tên name.

Bạn không thể sử dụng thuộc tính này với namespace.name.link.other.allow_all_shared_libs.

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

Điều này cho biết rằng đường liên kết dự phòng chỉ chấp nhận libc.so hoặc libm.so làm tên thư viện được yêu cầu. Trình liên kết động sẽ bỏ qua đường liên kết dự phòng từ sphal đến không gian tên default nếu tên thư viện được yêu cầu không phải là libc.so hoặc libm.so.

namespace.name.link.other.allow_all_shared_libs

Giá trị boolean cho biết liệu có thể tìm kiếm tất cả thư viện dùng chung trong không gian tên other hay không khi không tìm thấy các thư viện đó trong không gian tên name.

Bạn không thể sử dụng thuộc tính này với namespace.name.link.other.shared_libs.

namespace.vndk.link.sphal.allow_all_shared_libs = true

Điều này cho biết rằng tất cả tên thư viện đều có thể đi qua đường liên kết dự phòng từ không gian tên vndk đến sphal.

Thuộc tính không gian tên

Thuộc tính Mô tả Ví dụ
namespace.name.isolated

Giá trị boolean cho biết trình liên kết động có nên kiểm tra vị trí của thư viện chia sẻ hay không.

Nếu isolatedtrue, thì chỉ các thư viện dùng chung nằm trong một trong các thư mục search.paths (không bao gồm thư mục con) hoặc thuộc một trong các thư mục permitted.paths (bao gồm cả thư mục con) mới có thể được tải.

Nếu isolatedfalse (mặc định), trình liên kết động sẽ không kiểm tra đường dẫn của thư viện dùng chung.

namespace.sphal.isolated = true

Điều này cho biết rằng chỉ các thư viện dùng chung trong search.paths hoặc trong permitted.paths mới có thể được tải vào không gian tên sphal.

namespace.name.search.paths

Danh sách các thư mục được phân tách bằng dấu hai chấm để tìm kiếm thư viện chia sẻ.

Các thư mục được chỉ định trong search.paths được thêm vào đầu tên thư viện được yêu cầu nếu các lệnh gọi hàm đến mục dlopen() hoặc DT_NEEDED không chỉ định đường dẫn đầy đủ. Thư mục được chỉ định ở đầu danh sách có mức độ ưu tiên cao hơn.

Khi isolatedtrue, bạn có thể tải các thư viện dùng chung trong một trong các thư mục search.paths (ngoại trừ thư mục con) bất kể thuộc tính permitted.paths.

Ví dụ: nếu search.paths/system/${LIB}permitted.paths trống, thì bạn có thể tải /system/${LIB}/libc.so nhưng không thể tải /system/${LIB}/vndk/libutils.so.

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

Điều này cho thấy rằng trình liên kết động sẽ tìm kiếm /system/${LIB} cho các thư viện dùng chung.

namespace.name.asan.search.paths

Danh sách thư mục được phân tách bằng dấu hai chấm để tìm thư viện dùng chung khi AddressSanitizer (ASan) được bật.

namespace.name.search.paths sẽ bị bỏ qua khi bạn bật ASan.

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

Điều này cho biết rằng khi bạn bật ASan, trình liên kết động sẽ tìm kiếm /data/asan/system/${LIB} trước rồi tìm kiếm /system/${LIB}.

namespace.name.permitted.paths

Danh sách các thư mục (bao gồm cả thư mục con) được phân tách bằng dấu hai chấm, trong đó trình liên kết động có thể tải thư viện dùng chung (ngoài search.paths) khi isolatedtrue.

Bạn cũng có thể tải các thư viện dùng chung nằm trong thư mục con của permitted.paths. Ví dụ: nếu permitted.paths/system/${LIB}, thì bạn có thể tải cả /system/${LIB}/libc.so/system/${LIB}/vndk/libutils.so.

Nếu isolatedfalse, permitted.paths sẽ bị bỏ qua và một cảnh báo sẽ được phát ra.

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

Điều này cho biết rằng các thư viện dùng chung trong /system/${LIB}/hw có thể được tải vào không gian tên default riêng biệt.

Ví dụ: nếu không có permitted.paths, libaudiohal.so sẽ không thể tải /system/${LIB}/hw/audio.a2dp.default.so vào không gian tên default.

namespace.name.asan.permitted.paths

Danh sách các thư mục được phân tách bằng dấu hai chấm mà trình liên kết động có thể tải thư viện dùng chung khi bạn bật ASan.

namespace.name.permitted.paths sẽ bị bỏ qua khi bạn bật ASan.

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

Điều này cho biết rằng khi bật ASan, bạn có thể tải các thư viện dùng chung trong /data/asan/system/${LIB}/hw hoặc /system/${LIB}/hw vào không gian tên default riêng biệt.

namespace.name.visible

Giá trị boolean cho biết liệu chương trình (ngoài libc) có thể lấy một tay cầm không gian tên trình liên kết bằng android_get_exported_namespace() và mở một thư viện dùng chung trong không gian tên trình liên kết bằng cách truyền tay cầm đến android_dlopen_ext() hay không.

Nếu visibletrue, thì android_get_exported_namespace() luôn trả về tên người dùng nếu không gian tên tồn tại.

Nếu visiblefalse (mặc định), thì android_get_exported_namespace() luôn trả về NULL bất kể có không gian tên hay không. Bạn chỉ có thể tải thư viện dùng chung vào không gian tên này nếu (1) thư viện được yêu cầu bởi một không gian tên trình liên kết khác có đường liên kết dự phòng đến không gian tên này hoặc (2) thư viện được yêu cầu bởi các thư viện dùng chung hoặc tệp thực thi khác trong không gian tên này.

namespace.sphal.visible = true

Điều này cho biết rằng android_get_exported_namespace("sphal") có thể trả về một tay cầm không gian tên trình liên kết hợp lệ.

Tạo không gian tên trình liên kết

Trong Android 11, cấu hình trình liên kết được tạo trong thời gian chạy trong /linkerconfig thay vì sử dụng tệp văn bản thuần tuý trong ${android-src}/system/core/rootdir/etc. Cấu hình được tạo tại thời điểm khởi động dựa trên môi trường thời gian chạy, bao gồm các mục sau:

  • Nếu thiết bị hỗ trợ VNDK
  • Phiên bản VNDK mục tiêu của phân vùng nhà cung cấp
  • Phiên bản VNDK của phân vùng sản phẩm
  • Các mô-đun APEX đã cài đặt

Cấu hình trình liên kết được tạo bằng cách phân giải các phần phụ thuộc giữa các không gian tên của trình liên kết. Ví dụ: nếu có bất kỳ nội dung cập nhật nào trên các mô-đun APEX có chứa thông tin cập nhật phần phụ thuộc, thì cấu hình trình liên kết sẽ được tạo để phản ánh những thay đổi này. Bạn có thể xem thêm thông tin chi tiết về cách tạo cấu hình trình liên kết trong ${android-src}/system/linkerconfig.

Tách biệt không gian tên của trình liên kết

Có 3 loại cấu hình. Tuỳ thuộc vào giá trị của PRODUCT_TREBLE_LINKER_NAMESPACESBOARD_VNDK_VERSION trong BoardConfig.mk, cấu hình tương ứng sẽ được tạo tại thời điểm khởi động.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Cấu hình đã chọn Yêu cầu về VTS
true current VNDK Bắt buộc đối với các thiết bị chạy Android 9 trở lên
Trống VNDK Lite Bắt buộc đối với các thiết bị chạy Android 8.x
false Trống Legacy Đối với các thiết bị không phải Treble

Cấu hình VNDK Lite tách biệt các thư viện dùng chung SP-HAL và VNDK-SP. Trong Android 8.0, đây phải là tệp cấu hình cho trình liên kết động khi PRODUCT_TREBLE_LINKER_NAMESPACEStrue.

Cấu hình VNDK cũng tách biệt các thư viện dùng chung SP-HAL và VNDK-SP. Ngoài ra, cấu hình này cung cấp tính năng tách biệt trình liên kết động đầy đủ. Điều này đảm bảo rằng các mô-đun trong phân vùng hệ thống sẽ không phụ thuộc vào thư viện dùng chung trong phân vùng của nhà cung cấp và ngược lại.

Trên Android 8.1 trở lên, cấu hình VNDK là cấu hình mặc định và bạn nên bật hoàn toàn tính năng tách biệt trình liên kết động bằng cách đặt BOARD_VNDK_VERSION thành current.

Cấu hình VNDK

Cấu hình VNDK tách biệt các phần phụ thuộc thư viện dùng chung giữa phân vùng hệ thống và phân vùng nhà cung cấp. So với các cấu hình được đề cập trong tiểu mục trước, sự khác biệt được nêu như sau:

  • Quy trình khung

    • Tạo không gian tên default, vndk, sphalrs.
    • Tất cả các không gian tên đều được tách biệt.
    • Thư viện dùng chung của hệ thống được tải vào không gian tên default.
    • SP-HAL được tải vào không gian tên sphal.
    • Thư viện dùng chung VNDK-SP được tải vào không gian tên vndk.
  • Quy trình của nhà cung cấp

    • Tạo không gian tên default, vndksystem.
    • Không gian tên default được tách biệt.
    • Thư viện dùng chung của nhà cung cấp được tải vào không gian tên default.
    • Thư viện dùng chung VNDK và VNDK-SP được tải vào không gian tên vndk.
    • LL-NDK và các phần phụ thuộc của nó được tải vào không gian tên system.

Mối quan hệ giữa các không gian tên trình liên kết được minh hoạ dưới đây.

Biểu đồ không gian tên của trình liên kết được mô tả trong cấu hình VNDK

Hình 1. Cách ly không gian tên trình liên kết (cấu hình VNDK).

Trong hình trên, LL-NDKVNDK-SP là viết tắt của các thư viện dùng chung sau:

  • 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

Bạn có thể xem thêm thông tin chi tiết trong /linkerconfig/ld.config.txt trên thiết bị.

Cấu hình VNDK Lite

Kể từ Android 8.0, trình liên kết động được định cấu hình để tách biệt các thư viện dùng chung SP-HAL và VNDK-SP sao cho các biểu tượng của chúng không xung đột với các thư viện dùng chung khung khác. Mối quan hệ giữa các không gian tên trình liên kết được thể hiện dưới đây.

Biểu đồ không gian tên của trình liên kết được mô tả trong cấu hình VNDK Lite
Hình 2. Tách biệt không gian tên trình liên kết (cấu hình VNDK Lite)

LL-NDKVNDK-SP là viết tắt của các thư viện dùng chung sau:

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libstdc++.so (không có trong cấu hình)
    • libsync.so
    • libvndksupport.so
    • libz.so (được chuyển sang VNDK-SP trong cấu hình)
  • 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

Bảng dưới đây liệt kê cấu hình không gian tên cho các quy trình khung, được trích từ phần [system] trong cấu hình VNDK Lite.

Không gian tên Thuộc tính Giá trị
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 (dành cho 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 (dành cho 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 (dành cho nhân RS đã biên dịch)
isolated true
visible true
links default,vndk
link.default.shared_libs LL-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

Bảng dưới đây trình bày cấu hình không gian tên cho các quy trình của nhà cung cấp, được trích từ phần [vendor] trong cấu hình VNDK Lite.

Không gian tên Thuộc tính Giá trị
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} (không dùng nữa)
/product/${LIB} (không dùng nữa)
isolated false

Bạn có thể xem thêm thông tin chi tiết trong /linkerconfig/ld.config.txt trên thiết bị.

Nhật ký tài liệu

Các thay đổi về Android 11

  • Trong Android 11, các tệp ld.config.*.txt tĩnh sẽ bị xoá khỏi cơ sở mã và LinkerConfig sẽ tạo các tệp đó trong thời gian chạy.

Các thay đổi đối với Android 9

  • Trong Android 9, không gian tên trình liên kết vndk được thêm vào các quy trình của nhà cung cấp và các thư viện dùng chung VNDK được tách biệt với không gian tên trình liên kết mặc định.
  • Thay thế PRODUCT_FULL_TREBLE bằng PRODUCT_TREBLE_LINKER_NAMESPACES cụ thể hơn.
  • Android 9 thay đổi tên của các tệp cấu hình trình liên kết động sau.
    Android 8.x Android 9 Mô tả
    ld.config.txt.in ld.config.txt Đối với các thiết bị có tính năng tách biệt không gian tên trình liên kết thời gian chạy
    ld.config.txt ld.config.vndk_lite.txt Đối với các thiết bị được tách biệt không gian tên của trình liên kết VNDK-SP
    ld.config.legacy.txt ld.config.legacy.txt Đối với các thiết bị cũ chạy Android 7.x trở xuống
  • Xoá android.hardware.graphics.allocator@2.0.so.
  • Thêm phân vùng productodm.