در این صفحه، شما یاد خواهید گرفت که چگونه کتابخانه C/C++ سندباکس شده خود را با API سندباکس شده (SAPI) ایجاد کنید. از آن به عنوان راهنما در کنار مثالها و مستندات کد در فایلهای هدر استفاده کنید.
ساخت وابستگیها
وابستگیهای زیر باید روی سیستم نصب شوند:
- هسته لینوکس با پشتیبانی از UTS، IPC، کاربر، PID و فضاهای نام شبکه
- هدرهای API فضای کاربری لینوکس
- برای کامپایل کد خود: GCC 6 (نسخه ۷ یا بالاتر ترجیح داده میشود) یا Clang 7 (یا بالاتر)
- برای تولید خودکار فایلهای هدر: Clang Python Bindings
- پایتون ۳.۵ یا بالاتر
- Bazel نسخه ۲.۲.۰ یا CMake نسخه ۳.۱۲ یا بالاتر.
استفاده از بازل
Bazel سیستم ساخت پیشنهادی است و ادغام با آن آسانترین است.
مستندات ما از کامپایلر Clang استفاده میکند. اگر به یک زنجیره ابزار خاص (مثلاً کامپایلر، لینکر و غیره) نیاز دارید، برای اطلاعات در مورد نحوه تغییر زنجیره ابزار کامپایلر پیشفرض، به مستندات Bazel مراجعه کنید.
دبیان ۱۰ (باستر)
برای نصب وابستگیهای ساخت:
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
جنتو
گزینههای مورد نیاز هسته:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
برای نصب وابستگیهای ساخت:
emerge dev-util/bazel dev-python/typing dev-python/clang-pythonاستفاده از CMake
CMake یک سیستم متا بیلد متنباز محبوب است که فایلهای پروژه را برای ابزارهای ساخت مانند Ninja یا Make تولید میکند.
دبیان ۱۰ (باستر)
برای نصب وابستگیهای ساخت:
sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \ python3 python3-pip libclang-dev libcap-devpip3 install absl-py clang
جنتو
گزینههای مورد نیاز هسته:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
برای نصب وابستگیهای ساخت:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-pythonفرآیند توسعه
برای سندباکس کردن یک کتابخانه C/C++، باید دو مورد را برای پروژه خود آماده کنید:
- کتابخانه سندباکس شده
- کد میزبان که از قابلیتهای ارائه شده توسط کتابخانه Sandboxed شما استفاده خواهد کرد. SAPI شیء SAPI و RPC Stub را به طور خودکار در طول فرآیند ساخت برای شما تولید میکند.
ممکن است با zlib از مثالهای Sandbox2 آشنا باشید، در اینجا کل یک برنامه ( zpipe.c ) در sandbox قرار داده شده است. در مراحل زیر، نحوه استفاده از SAPI برای sandbox کردن کتابخانه zlib و استفاده از کتابخانه Sandboxed را خواهید آموخت.
۱. تصمیم بگیرید که کدام توابع مورد نیاز هستند
اگر به کد میزبان zlib ( main_zlib.cc ) نگاه کنید، میتوانید ببینید که عملکرد این ابزار خواندن دادهها از stdin و استفاده از تابع deflate() در zlib برای فشردهسازی دادهها تا زمان خوانده شدن نشانگر EOF است. در مجموع، این برنامه از سه تابع zlib استفاده میکند:
-
deflateInit_(): برای مقداردهی اولیه جهت فشردهسازی -
deflate(): برای انجام عملیات فشردهسازی روی تکه داده -
deflateEnd(): برای پایان دادن به فشردهسازی و آزاد کردن ساختارهای دادهای که به صورت پویا تخصیص داده شدهاند.
در یک مثال واقعی، شما کتابخانه C/C++ را بررسی میکنید و تصمیم میگیرید که به کدام توابع نیاز دارید. یک استراتژی ممکن این است که با کد میزبان شروع کنید و از کتابخانه بدون سندباکس استفاده کنید. سپس، در مرحله دوم، میتوانید کتابخانه سندباکس شده را ایجاد کنید و کد میزبان را برای استفاده از فراخوانیهای تابع سندباکس شده تطبیق دهید.
۲. قانون ساخت sapi_library را بنویسید
پس از اینکه سه تابع zlib مورد نیاز را از کتابخانه zlib که در محیط sandbox قرار دارد، شناسایی کردید، میتوانید قانون ساخت را در فایل BUILD تعریف کنید. مستندات مربوط به قانون ساخت sapi_library را میتوانید در صفحه قوانین ساخت (Build Rules) بیابید.
قطعه کد زیر تعریف sapi_library را برای مثال zlib SAPI نشان میدهد. با استفاده از ویژگی lib ، به Bazel دستور داده میشود که در فایل WORKSPACE به دنبال کتابخانه zlib بگردد.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
نتیجه این است که کتابخانه zlib در حالت sandbox تولید میشود. خروجی، شیء SAPI است که میتواند در کد میزبان گنجانده شود و برای ارتباط با کتابخانه در حالت sandbox از طریق فراخوانیهای RPC استفاده شود. سیاست Sandbox که در این مثال استفاده شده است، سیاست پیشفرض است.
۳. کد میزبان را بنویسید یا تغییر دهید
اکنون زمان آن رسیده است که کتابخانه SAPI تولید شده را در کد میزبان (Host Code) بگنجانیم.
ایجاد جعبه شنی
برای ایجاد یک شیء sandbox 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 :
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 نگاهی بیندازید.
مثالها
در بخش «مثالها» میتوانید چند کتابخانه پیدا کنید که از قبل توسط تیم SAPI آماده شدهاند.