בדף הזה נסביר איך ליצור ספריית 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 ואילך.
שימוש ב-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++, עליך להכין שני פריטים לפרויקט:
- הספרייה בארגז חול
- קוד המארח שישתמש בפונקציונליות שנחשפת על ידי הספרייה בארגז החול. SAPI ייצור עבורך את SAPI Object ואת RPC Stub באופן אוטומטי במהלך תהליך ה-build.
ייתכן שאתם מכירים את ה-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.