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

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

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

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

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

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

תצורת הקישור נוצרת על ידי פתרון יחסי התלות בין מרחבי השמות של הקישור. לדוגמה, אם יש עדכונים במודולים של APEX שכוללים עדכוני יחסי תלות, הגדרות הקישור נוצרות בהתאם לשינויים האלה. פרטים נוספים על יצירת הגדרות לקישור זמינים ב-${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. בידוד של מרחב השמות של ה-Linker (הגדרת 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

בטבלה הבאה מפורטות הגדרות שמות המרחבים לתהליכי המסגרת, והיא מובאת מתוך הקטע [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 הסטטיים הוסרו מקוד המקור, ובמקום זאת 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.