ในหน้านี้ คุณจะได้เรียนรู้วิธีสร้างไลบรารี C/C++ แบบแซนด์บ็อกซ์ของคุณเองด้วย Sandboxed API (SAPI) ใช้เป็นแนวทางควบคู่ไปกับตัวอย่างและเอกสารประกอบโค้ดในไฟล์ส่วนหัว
ทรัพยากร Dependency ของบิลด์
ต้องติดตั้งการอ้างอิงต่อไปนี้ในระบบ
- เคอร์เนล 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 หากต้องการ Toolchain ที่เฉพาะเจาะจง (เช่น คอมไพเลอร์ ลิงก์เกอร์ ฯลฯ) โปรดดูเอกสารประกอบของ Bazel เพื่อดูข้อมูลเกี่ยวกับวิธีเปลี่ยน Toolchain ของคอมไพเลอร์เริ่มต้น
Debian 10 (Buster)
วิธีติดตั้งการอ้างอิงบิลด์
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
วิธีติดตั้งการอ้างอิงบิลด์
emerge dev-util/bazel dev-python/typing dev-python/clang-python
การใช้ CMake
CMake เป็นระบบการสร้างเมตาแบบโอเพนซอร์สที่ได้รับความนิยม ซึ่ง สร้างไฟล์โปรเจ็กต์สำหรับเครื่องมือบิลด์ เช่น Ninja หรือ Make
Debian 10 (Buster)
วิธีติดตั้งการอ้างอิงบิลด์
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
วิธีติดตั้งการอ้างอิงบิลด์
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python
กระบวนการพัฒนา
หากต้องการแซนด์บ็อกซ์ไลบรารี C/C++ คุณจะต้องเตรียม 2 รายการสำหรับโปรเจ็กต์
- ไลบรารีที่แยกในแซนด์บ็อกซ์
- โค้ดโฮสต์ซึ่งจะใช้ฟังก์ชันการทำงานที่ไลบรารี Sandbox แสดง SAPI จะสร้างออบเจ็กต์ SAPI และ RPC Stub ให้คุณโดยอัตโนมัติในระหว่างกระบวนการบิลด์
คุณอาจคุ้นเคยกับ zlib จากตัวอย่าง Sandbox2 ที่นี่ซึ่งมีการแซนด์บ็อกซ์โปรแกรมทั้งหมด (zpipe.c) ในขั้นตอนต่อไปนี้ คุณจะได้เรียนรู้วิธีใช้ SAPI เพื่อ แซนด์บ็อกซ์ไลบรารี zlib และ ใช้ประโยชน์จากไลบรารีแซนด์บ็อกซ์
1. ตัดสินใจเลือกฟังก์ชันที่ต้องการ
หากดูโค้ดโฮสต์ zlib
(main_zlib.cc)
คุณจะเห็นว่าฟังก์ชันการทำงานของเครื่องมือนี้คือการอ่านข้อมูลจาก stdin และใช้ฟังก์ชัน deflate()
ของ zlib เพื่อบีบอัดข้อมูลจนกว่าจะอ่านเครื่องหมาย EOF
โดยรวมแล้ว โปรแกรมจะใช้ฟังก์ชัน 3 รายการจาก zlib ดังนี้
deflateInit_()
: เริ่มต้นสำหรับการบีบอัดdeflate()
: เพื่อดำเนินการบีบอัดในก้อนข้อมูลdeflateEnd()
: เพื่อสิ้นสุดการบีบอัดและโครงสร้างข้อมูลที่จัดสรรแบบไดนามิกฟรี
ในตัวอย่างการใช้งานจริง คุณจะต้องตรวจสอบไลบรารี C/C++ และตัดสินใจว่าต้องการฟังก์ชันใด กลยุทธ์ที่เป็นไปได้คือการเริ่มต้นด้วยรหัสโฮสต์และใช้ไลบรารีที่ไม่ได้อยู่ในแซนด์บ็อกซ์ จากนั้นในขั้นตอนที่ 2 คุณจะสร้าง ไลบรารีแซนด์บ็อกซ์และปรับโค้ดโฮสต์ให้ใช้การเรียกฟังก์ชันแซนด์บ็อกซ์ได้
2. เขียนกฎการสร้าง sapi_library
หลังจากระบุฟังก์ชัน zlib 3 รายการที่จำเป็นจากไลบรารี zlib ที่อยู่ในแซนด์บ็อกซ์แล้ว คุณจะกำหนดกฎการสร้างในไฟล์ BUILD ได้
ดูเอกสารประกอบสำหรับsapi_library
กฎการสร้างได้ในหน้ากฎการสร้าง
ข้อมูลโค้ดด้านล่างแสดงsapi_library
คําจํากัดความสําหรับ SAPI ของ zlib
ตัวอย่าง การใช้แอตทริบิวต์ 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
Object หากตัดสินใจใช้แนวทาง "เปลี่ยน" คุณต้องตรวจสอบว่า
พารามิเตอร์ฟังก์ชันตรงกับค่าที่คาดไว้
ตัวอย่างการเรียกแต่ละครั้งใน 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
ตัวอย่าง
ในส่วนตัวอย่าง คุณจะเห็นไลบรารี 2-3 รายการ ที่ทีม SAPI เตรียมไว้ให้แล้ว