בדף הזה נסביר איך ליצור ספריית C/C++ משלכם עם ארגז חול באמצעות Sandboxed API (SAPI). אפשר להיעזר בו לצד הדוגמאות והתיעוד של הקוד בקובצי הכותרת.
יחסי תלות ב-Build
צריך להתקין במערכת את יחסי התלות הבאים:
- ליבת 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 היא מערכת הבנייה המומלצת והכי קלה לשילוב.
במסמכי התיעוד שלנו אנחנו משתמשים במהדר 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 היא מערכת פופולרית בקוד פתוח ליצירת קובצי פרויקט עבור כלי בנייה כמו 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++, צריך להכין שני פריטים לפרויקט:
- הספרייה שמופעלת בארגז חול
- קוד המארח שישתמש בפונקציונליות שמוצגת על ידי הספרייה בתוך ארגז החול. SAPI ייצור באופן אוטומטי את אובייקט SAPI ואת RPC Stub במהלך תהליך הבנייה.
יכול להיות שאתם מכירים את 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.
בקטע הקוד הבא מוצגת ההגדרה של zlib SAPI לדוגמה.sapi_library
באמצעות המאפיין 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.