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

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

יצירת יחסי תלות

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

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

שימוש ב-Bazel

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

בתיעוד שלנו נעשה שימוש במהדר Clang. אם יש צורך בשרשרת כלים ספציפית (למשל, מהדר, מקשר וכו'), במסמכי התיעוד של 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

ג'נטו

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

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 פופולרית בקוד פתוח, שיוצרת קובצי פרויקט לכלי 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

ג'נטו

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

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 כדי לארגז חול (sandbox) של ספריית zlib ולהשתמש בספרייה Sandboxed.

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

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

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

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

2. כתיבת כלל הבנייה של sapi_library

לאחר שזיהית את שלוש פונקציות zlib הדרושות מספריית zlib בארגז החול, ניתן להגדיר את כלל ה-build בקובץ 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. מדיניות Sandbox שנעשה בה שימוש בדוגמה זו היא מדיניות ברירת המחדל.

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

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

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

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

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

שימוש בסוגי SAPI

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

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

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

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

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

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

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

  • 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 מתקדמת צעד אחד קדימה וחוזרת באופן אוטומטי על תהליכים שנכשלו.

פרטים נוספים זמינים בדף העסקאות של SAPI.

דוגמאות

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