מרחב שמות של מקשר

המקשר הדינמי מטפל בשני אתגרים בתכנון של Treble VNDK:

  • ספריות משותפות של SP-HAL ויחסי התלות שלהן, כולל ספריות VNDK-SP, נטענות בתהליכי המסגרת. צריכים להיות מנגנונים מסוימים למניעת התנגשויות בין סמלים.
  • dlopen() ו-android_dlopen_ext() יכולים להוסיף יחסי תלות מסוימים בסביבת זמן הריצה שלא גלויים בזמן ה-build, וקשה לזהות אותם באמצעות ניתוח סטטי.

אפשר לפתור את שתי הבעיות האלה באמצעות המנגנון של מרחב השמות של הקישור. המנגנון הזה מסופק על ידי הקישור הדינמי. הוא יכול לבודד את הספריות המשותפות במרחבי שמות שונים של קישורים, כדי שלא יהיו התנגשויות בין ספריות עם אותו שם ספרייה אבל עם סמלים שונים.

לעומת זאת, המנגנון של מרחב השמות של ה-linker מספק את הגמישות שמאפשרת לייצא ספריות משותפות מסוימות באמצעות מרחב שמות של linker ולהשתמש בהן באמצעות מרחב שמות אחר של linker. ספריות משותפות שיוצאו יכולות להפוך לממשקי תכנות ל-Application (API) שגלויים לתוכנות אחרות, תוך הסתרת פרטי ההטמעה שלהן במרחבי השמות של ה-linker.

לדוגמה, /system/lib[64]/libcutils.so ו-/system/lib[64]/vndk-sp-${VER}/libcutils.so הן שתי ספריות משותפות. לכל אחת משתי הספריות האלה יכולים להיות סמלים שונים. הם נטענים במרחבי שמות שונים של קישורים, כדי שממשקי ה-framework יוכלו להסתמך על /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, כמו 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

המשמעות היא שיש שלושה מרחבי שמות (default,‏ sphal ו-vndk) בתצורה של [system].

namespace.name.links

רשימה מופרדת בפסיקים של מרחבי שמות חלופיים.

אם לא ניתן למצוא ספרייה משותפת במרחב השמות הנוכחי, הקישור הדינמי מנסה לטעון את הספרייה המשותפת ממרחב השמות החלופי. למרחב השמות שצוין בתחילת הרשימה יש עדיפות גבוהה יותר.

namespace.sphal.links = default,vndk

אם ספרייה משותפת או קובץ הפעלה מבקשים ספרייה משותפת שלא ניתן לטעון למרחב השמות sphal, מחבר הקבצים הדינמי מנסה לטעון את הספרייה המשותפת ממרחב השמות default.

לאחר מכן, אם לא ניתן לטעון את הספרייה המשותפת גם ממרחב השמות default, המנגנון לקישור הדינמי ינסה לטעון את הספרייה המשותפת ממרחב השמות vndk.

לבסוף, אם כל הניסיונות נכשלים, הקישור הדינמי מחזיר שגיאה.

namespace.name.link.other.shared_libs

רשימה של ספריות משותפות מופרדות בפסיקים, שאפשר לחפש אותן במרחבי השמות other כשלא ניתן למצוא אותן במרחב השמות name.

לא ניתן להשתמש בנכס הזה עם namespace.name.link.other.allow_all_shared_libs.

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

המשמעות היא שאפשר להזין בקישור החלופי רק את הערכים libc.so או libm.so בתור שם הספרייה המבוקש. המנגנון לקישור דינמי מתעלם מהקישור החלופי מ-sphal למרחב השמות default אם שם הספרייה המבוקש אינו libc.so או libm.so.

namespace.name.link.other.allow_all_shared_libs

ערך בוליאני שמציין אם אפשר לחפש את כל הספריות המשותפות במרחב השמות other כשאי אפשר למצוא אותן במרחב השמות name.

אי אפשר להשתמש בנכס הזה עם namespace.name.link.other.shared_libs.

namespace.vndk.link.sphal.allow_all_shared_libs = true

המשמעות היא שכל שמות הספריות יכולים לעבור דרך הקישור החלופי ממרחב השמות vndk למרחב השמות sphal.

מאפיינים של מרחב שמות

נכס תיאור דוגמה
namespace.name.isolated

ערך בוליאני שמציין אם המקשר הדינמי צריך לבדוק את מיקום הספרייה המשותפת.

אם הערך של isolated הוא true, אפשר לטעון רק את הספריות המשותפות שנמצאות ב אחת מהספריות search.paths (לא כולל ספריות משנה) או שנמצאות מתחת לאחת מהספריות permitted.paths (כולל ספריות משנה).

אם הערך של isolated הוא false (ברירת המחדל), הקישור הדינמי לא בודק את הנתיב של הספריות המשותפות.

namespace.sphal.isolated = true

המשמעות היא שרק הספריות המשותפות ב-search.paths או ב-permitted.paths יכולות להיטען במרחב השמות sphal.

namespace.name.search.paths

רשימה של ספריות שמופרדות בפסיקים, שבהן יתבצע חיפוש של ספריות משותפות.

הספריות שצוינו ב-search.paths מתווספות לתחילת שם הספרייה המבוקש, אם בקריאות הפונקציה ל-dlopen() או לרשומה DT_NEEDED לא צוין הנתיב המלא. הספרייה שצוינה בתחילת הרשימה תקבל עדיפות גבוהה יותר.

כשהערך של isolated הוא true, אפשר לטעון ספריות משותפות שנמצאות ב אחת מהספריות 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.default.asan.search.paths = /data/asan/system/${LIB}:/system/${LIB}

המשמעות היא שכאשר ASan מופעל, ה-linker הדינמי מחפש קודם את /data/asan/system/${LIB} ואז את /system/${LIB}.

namespace.name.permitted.paths

רשימה של ספריות (כולל ספריות משנה) מופרדות בפסיקים, שבהן הקישור הדינמי יכול לטעון את הספריות המשותפות (בנוסף ל-search.paths) כש-isolated הוא true.

אפשר גם לטעון את הספריות המשותפות שנמצאות בתיקיות המשנה של permitted.paths. לדוגמה, אם permitted.paths הוא /system/${LIB}, אפשר לטעון גם את /system/${LIB}/libc.so וגם את /system/${LIB}/vndk/libutils.so.

אם הערך של isolated הוא false, המערכת מתעלמת מ-permitted.paths ומופיעה אזהרה.

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

המשמעות היא שאפשר לטעון את הספריות המשותפות שמתחת למרחב השמות /system/${LIB}/hw למרחב השמות המבודד default.

לדוגמה, בלי permitted.paths,‏ libaudiohal.so לא יכול לטעון את /system/${LIB}/hw/audio.a2dp.default.so למרחב השמות default.

namespace.name.asan.permitted.paths

רשימה של ספריות מופרדות בפסיקים שבהן המקשר הדינמי יכול לטעון את הספריות המשותפות כש-ASan מופעל.

המערכת מתעלמת מ-namespace.name.permitted.paths כשASan מופעל.

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().

אם הערך של visible הוא true, הפונקציה android_get_exported_namespace() תמיד מחזירה את הכינוי אם מרחב השמות קיים.

אם הערך של visible הוא false (ברירת המחדל), הפונקציה android_get_exported_namespace() תמיד מחזירה את הערך NULL, ללא קשר לנוכחות של מרחב השמות. אפשר לטעון ספריות משותפות למרחב השמות הזה רק אם (1) הן נדרשות על ידי מרחב שמות אחר של קישור שיש לו קישור חלופי למרחב השמות הזה, או (2) הן נדרשות על ידי ספריות משותפות או קובצי הפעלה אחרים במרחב השמות הזה.

namespace.sphal.visible = true

האפשרות הזו מציינת ש-android_get_exported_namespace("sphal") יכול להחזיר כינוי חוקי של מרחב שמות לקישורים.

יצירת מרחב שמות של קישורים

ב-Android 11, הגדרות ה-linker נוצרות בזמן הריצה עם הפקודה /linkerconfig במקום להשתמש בקובצי טקסט פשוט ב-${android-src}/system/core/rootdir/etc. ההגדרות נוצרות בזמן האתחול על סמך סביבת זמן הריצה, שכוללת את הפריטים הבאים:

  • אם המכשיר תומך ב-VNDK
  • גרסת היעד של VNDK במחיצה של הספק
  • גרסת VNDK של חלוקת המוצרים
  • מודולים מותקנים של APEX

תצורת הקישור נוצרת על ידי פתרון יחסי התלות בין מרחבי השמות של הקישור. לדוגמה, אם יש עדכונים במודולים של APEX שכוללים עדכונים של תלות, הגדרת ה-linker נוצרת שמשקפת את השינויים האלה. פרטים נוספים על יצירת הגדרות של קישורים זמינים במאמר ${android-src}/system/linkerconfig.

בידוד של מרחב השמות של מקשר

יש שלושה סוגי הגדרות. בהתאם לערך של PRODUCT_TREBLE_LINKER_NAMESPACES ו-BOARD_VNDK_VERSION ב-BoardConfig.mk, ההגדרות המתאימות נוצרות בזמן ההפעלה.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
ההגדרות האישיות שנבחרו דרישת VTS
true current VNDK חובה במכשירים שהושקו עם Android מגרסה 9 ואילך
ריק VNDK Lite חובה במכשירים שהושקו עם Android 8.x
false ריק Legacy במכשירים שאינם Treble

הגדרת VNDK Lite מבודדת ספריות משותפות של SP-HAL ו-VNDK-SP. ב-Android 8.0, זהו קובץ התצורה של קישור דינמי כש-PRODUCT_TREBLE_LINKER_NAMESPACES הוא true.

הגדרת VNDK מבודדת גם את הספריות המשותפות של SP-HAL ו-VNDK-SP. בנוסף, ההגדרה הזו מספקת את הבידוד המלא של קישור הדינמי. כך מוודאים שהמודולים במחיצה של המערכת לא יהיו תלויים בספריות המשותפות במחיצות של הספקים, ולהפך.

ב-Android מגרסה 8.1 ואילך, הגדרת VNDK היא הגדרת ברירת המחדל, ומומלץ מאוד להפעיל בידוד מלא של קישור דינמי על ידי הגדרת BOARD_VNDK_VERSION ל-current.

הגדרת VNDK

ההגדרה של VNDK מבודדת את יחסי התלות בספריות המשותפות בין מחיצת המערכת למחיצות של הספקים. בהשוואה להגדרות שצוינו בקטע הקודם, ההבדלים הם:

  • תהליכים של Framework

    • נוצרים מרחבי השמות default,‏ vndk,‏ sphal ו-rs.
    • כל מרחבי השמות מבודדים.
    • ספריות משותפות של המערכת נטענות למרחב השמות default.
    • דפי SP-HAL נטענים למרחב השמות של sphal.
    • ספריות משותפות של VNDK-SP נטענות במרחב השמות vndk.
  • תהליכים של ספקים

    • נוצרים מרחבי השמות default, vndk ו-system.
    • מרחב השמות default מבודד.
    • ספריות משותפות של ספקים נטענות למרחב השמות default.
    • ספריות משותפות של VNDK ו-VNDK-SP נטענות למרחב השמות vndk.
    • LL-NDK והתלות שלו נטענים במרחב השמות system.

הקשר בין מרחבי השמות של ה-linker מוצג בהמשך.

תרשים של מרחב השמות של ה-Linker שמתואר בהגדרות של VNDK

איור 1. בידוד של מרחב השמות של המקשר (הגדרת VNDK).

בתמונה שלמעלה, LL-NDK ו-VNDK-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

החל מגרסה 8.0 של Android, הקישור הדינמי מוגדר לבודד את הספריות המשותפות של SP-HAL ו-VNDK-SP, כך שהסמלים שלהן לא ייכנסו לעימות עם ספריות משותפות אחרות של המסגרת. הקשר בין מרחבי השמות של ה-Linker מוצג בהמשך.

תרשים של מרחב השמות של ה-Linker שמתואר בתצורה של VNDK Lite
איור 2. בידוד של מרחב שמות של קישור (הגדרה של VNDK Lite)

LL-NDK ו-VNDK-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

הטבלה הבאה מפרטת את ההגדרות של מרחבי השמות לתהליכי framework, מתוך הקטע [system] בתצורה של VNDK Lite.

מרחב שמות נכס ערך
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

בטבלה הבאה מוצגת הגדרת שמות המרחבים לתהליכי הספקים, שהיא קטע מתוך הקטע [vendor] בתצורה של VNDK Lite.

מרחב שמות נכס ערך
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 הסטטיים מוסרים מ-codebase ו-LinkerConfig יוצר אותם בזמן ריצה.

שינויים ב-Android 9

  • ב-Android 9, מרחב השמות של ה-linker‏ vndk מתווסף לתהליכים של הספק, וספריות VNDK המשותפות מבודדות ממרחב השמות של ה-linker שמוגדר כברירת מחדל.
  • מחליפים את 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 במכשירים עם בידוד של מרחב השמות של ה-linker ב-VNDK-SP
    ld.config.legacy.txt ld.config.legacy.txt במכשירים ישנים עם Android מגרסה 7.x ומטה
  • מסירים את android.hardware.graphics.allocator@2.0.so.
  • נוספות המחיצות product ו-odm.