תחילת העבודה עם Sandboxed API

בדף הזה נסביר איך ליצור ספריית C/C++ משלכם עם ארגז חול באמצעות Sandboxed API‏ (SAPI). אפשר להיעזר בו לצד הדוגמאות והתיעוד של הקוד בקובצי הכותרת.

יחסי תלות ב-Build

צריך להתקין במערכת את יחסי התלות הבאים:

  • ליבת Linux עם תמיכה במרחבי שמות של UTS,‏ IPC,‏ user,‏ PID ורשת
  • כותרות של ממשקי API במרחב המשתמש של Linux
  • כדי לקמפל את הקוד: GCC 6 (מומלצת גרסה 7 ומעלה) או Clang 7 (או גרסה מתקדמת יותר)
  • ליצירה אוטומטית של קובצי כותרת: Clang Python Bindings
  • ‫Python 3.5 ואילך
  • Bazel בגרסה 2.2.0 או CMake בגרסה 3.12 ואילך.
    • ‫CMake בלבד: GNU Make או גרסה של כותרות הספרייה libcap וכלי בנייה כמו Ninja (מומלץ).

שימוש ב-Bazel

‫Bazel היא מערכת ה-build המומלצת, והיא הכי קלה לשילוב.

במסמכים שלנו אנחנו משתמשים בקומפיילר Clang. אם אתם צריכים שרשרת כלים ספציפית (למשל, קומפיילר, linker וכו'), תוכלו לעיין במסמכי Bazel כדי לקבל מידע על שינוי שרשרת הכלים של הקומפיילר שמוגדרת כברירת מחדל.

‫Debian 10 ‏ (Buster)

כדי להתקין יחסי תלות ב-build:

echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
  sudo tee /etc/apt/sources.list.d/bazel.list
wget -qO - https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install -qy build-essential linux-libc-dev bazel python3 \
  python3-pip libclang-dev
pip3 install clang

Gentoo

אפשרויות ליבה נדרשות:

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

כדי להתקין יחסי תלות ב-build:

emerge dev-util/bazel dev-python/typing dev-python/clang-python

שימוש ב-CMake

CMake היא מערכת build פופולרית בקוד פתוח לבניית מטא, שיוצרת קובצי פרויקט לכלים לבנייה כמו Ninja או Make.

‫Debian 10 ‏ (Buster)

כדי להתקין יחסי תלות ב-build:

sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \
  python3 python3-pip libclang-dev libcap-dev
pip3 install absl-py clang

Gentoo

אפשרויות ליבה נדרשות:

General setup  --->
-*- Namespaces support
[*]   UTS namespace
[*]   IPC namespace
[*]   User namespace (EXPERIMENTAL)
[*]   PID Namespaces
[*]   Network namespace

כדי להתקין יחסי תלות ב-build:

emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python

תהליך הפיתוח

כדי להפעיל ארגז חול לספריית C/C++‎, צריך להכין שני פריטים לפרויקט:

יכול להיות שאתם מכירים את zlib מהדוגמאות של Sandbox2. בדוגמה הזו, תוכנית שלמה (zpipe.c) הוכנסה לארגז חול. בשלבים הבאים נסביר איך להשתמש ב-SAPI כדי להפעיל את ספריית zlib בסביבת ארגז חול ולהשתמש בספרייה שמופעלת בסביבת ארגז חול.

1. מחליטים אילו פונקציות נדרשות

אם בודקים את קוד המארח של zlib‏ (main_zlib.cc), אפשר לראות שהפונקציונליות של הכלי היא לקרוא נתונים מ-stdin ולהשתמש בפונקציה deflate() של zlib כדי לדחוס את הנתונים עד שסמן EOF נקרא. בסך הכול, התוכנית משתמשת בשלוש פונקציות מ-zlib:

  • deflateInit_(): כדי לאתחל לדחיסה
  • deflate(): כדי לבצע את פעולת הדחיסה על נתח הנתונים
  • deflateEnd(): כדי לסיים את הדחיסה ולשחרר באופן דינמי מבני נתונים שהוקצו

בדוגמה מהחיים האמיתיים, בודקים את ספריית C/C++ ומחליטים אילו פונקציות נדרשות. אחת האפשרויות היא להתחיל עם קוד המארח ולהשתמש בספרייה ללא ארגז חול. בשלב השני, אפשר ליצור את הספרייה בתוך ארגז חול ולהתאים את קוד המארח לשימוש בקריאות לפונקציות בתוך ארגז החול.

2. כתיבת כלל הבנייה של ספריית ה-SAPI

אחרי שמזהים את שלוש פונקציות zlib שנדרשות מספריית zlib בסביבת ארגז חול, אפשר להגדיר את כלל הבנייה בקובץ BUILD. אפשר למצוא את התיעוד של כלל ה-build‏ sapi_library בדף Build Rules.

בקטע הקוד הבא מוצגת ההגדרה של sapi_library בדוגמה של zlib SAPI. באמצעות המאפיין lib, מערכת Bazel מקבלת הוראה לחפש את ספריית zlib בקובץ WORKSPACE.

sapi_library(
    name = "zlib-sapi",
    srcs = [],
    hdrs = [],
    functions = [
        "deflateInit_",
        "deflate",
        "deflateEnd",
    ],
    lib = "@net_zlib//:zlib",
    lib_name = "Zlib",
    namespace = "sapi::zlib",
)

התוצאה היא יצירה של ספריית zlib בארגז חול. הפלט הוא אובייקט SAPI שאפשר לכלול בקוד המארח ולהשתמש בו כדי לתקשר עם הספרייה בסביבת ארגז החול באמצעות קריאות RPC. מדיניות ארגז החול שמשמשת בדוגמה הזו היא מדיניות ברירת המחדל.

3. כתיבה או שינוי של קוד המארח

עכשיו צריך לשלב את ספריית ה-SAPI שנוצרה בקוד המארח.

יצירת ארגז החול

משתמשים ב-sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create()); כדי ליצור אובייקט ארגז חול.

משתמשים ב-sapi::zlib::ZlibApi api(&sandbox); כדי ליצור מופע של אובייקט SAPI וכך להפוך את הפונקציות בסביבת ארגז החול לזמינות לשימוש.

שימוש בסוגי SAPI

סוגי SAPI הם סוגים מיוחדים בצורה של מחלקות C++‎ ש-SAPI מספקת, כי לפעמים סוגי C רגילים לא יפעלו.

אפשר לראות את השימוש הראשון בסוג SAPI בהצהרה של strm, שבה נעשה שימוש במבנה SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;

סוג התבנית (sapi::zlib::z_stream) הוא דוגמה טובה לקוד שנוצר אוטומטית על ידי כלל הבנייה.

פרטים נוספים זמינים בדף המשתנים.

ביצוע קריאות ל-API

כדי להתקשר אל defalteInit_, אל deflate או אל deflateEnd, צריך להשתמש באובייקט SAPI. אם תבחרו להשתמש בגישה של 'שינוי', תצטרכו לוודא שפרמטרי הפונקציה תואמים לערכים הצפויים.

דוגמה לכל אחת מהקריאות ב-zlib example:

  • api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
        version.PtrBefore(), sizeof(sapi::zlib::z_stream));
  • api.deflate(strm.PtrBoth(), flush);
  • api.deflateEnd(strm.PtrBoth()).IgnoreError();

שימוש בעסקאות SAPI

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

פרטים נוספים זמינים בדף SAPI Transactions ‎.

דוגמאות

בקטע Examples אפשר למצוא כמה ספריות שכבר הוכנו על ידי צוות SAPI.