בדף הזה נסביר איך ליצור ספריית 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 ואילך.
שימוש ב-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.listwget -qO - https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -sudo apt-get updatesudo apt-get install -qy build-essential linux-libc-dev bazel python3 \ python3-pip libclang-devpip3 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-devpip3 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++, צריך להכין שני פריטים לפרויקט:
- הספרייה שמופעלת בארגז חול
- קוד המארח שישתמש בפונקציונליות שמוצגת על ידי הספרייה בתוך ארגז החול. SAPI ייצור באופן אוטומטי את אובייקט SAPI ואת RPC Stub במהלך תהליך build.
יכול להיות שאתם מכירים את 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.