Trên trang này, bạn sẽ tìm hiểu cách tạo thư viện C/C++ có hộp cát của riêng mình bằng API Hộp cát (SAPI). Hãy dùng phần này làm hướng dẫn cùng với ví dụ và tài liệu về mã trong các tệp tiêu đề.
Phần phụ thuộc của bản dựng
Các phần phụ thuộc sau phải được cài đặt trên hệ thống:
- Nhân Linux có hỗ trợ UTS, IPC, người dùng, PID và không gian tên mạng
- Tiêu đề API không gian người dùng Linux
- Để biên dịch mã của bạn: GCC 6 (ưu tiên phiên bản 7 trở lên) hoặc Clang 7 (trở lên)
- Đối với các tệp tiêu đề tạo tự động: Clang Python Bindings
- Python 3.5 trở lên
- Bazel phiên bản 2.2.0 hoặc CMake phiên bản 3.12 trở lên.
Dùng Bazel
Bazel là hệ thống xây dựng được đề xuất và dễ tích hợp nhất.
Tài liệu của chúng tôi sử dụng trình biên dịch Clang. Nếu bạn cần một chuỗi công cụ cụ thể (ví dụ: trình biên dịch, trình liên kết, v.v.), hãy tham khảo tài liệu về Bazel để biết thông tin về cách thay đổi chuỗi công cụ mặc định của trình biên dịch.
Debian 10 (Buster)
Cách cài đặt các phần phụ thuộc của bản dựng:
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
Cần có các tuỳ chọn kernel:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Cách cài đặt các phần phụ thuộc của bản dựng:
emerge dev-util/bazel dev-python/typing dev-python/clang-python
Sử dụng CMake
CMake là một hệ thống bản dựng meta nguồn mở phổ biến tạo tệp dự án cho các công cụ xây dựng như Ninja hoặc Make.
Debian 10 (Buster)
Cách cài đặt các phần phụ thuộc của bản dựng:
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
Cần có các tuỳ chọn kernel:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Cách cài đặt các phần phụ thuộc của bản dựng:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python
Quy trình phát triển
Để tạo hộp cát cho một thư viện C/C++, bạn sẽ phải chuẩn bị hai mục cho dự án của mình:
- Thư viện hộp cát
- Mã máy chủ lưu trữ sử dụng chức năng mà Thư viện hộp cát của bạn hiển thị. SAPI sẽ tự động tạo Đối tượng SAPI và Mã giả lập RPC cho bạn trong quá trình xây dựng.
Bạn có thể đã quen thuộc với zlib trong các ví dụ về Sandbox2 ở đây, toàn bộ chương trình (zpipe.c) được đặt trong hộp cát. Trong các bước sau, bạn sẽ tìm hiểu cách sử dụng SAPI để hộp cát cho thư viện zlib và tận dụng Thư viện hộp cát.
1. Quyết định những chức năng cần thiết
Nếu nhìn vào mã máy chủ zlib (main_zlib.cc), bạn có thể thấy chức năng của công cụ này là đọc dữ liệu từ stdin và dùng hàm deflate()
của zlib để nén dữ liệu cho đến khi điểm đánh dấu EOF
được đọc. Tổng cộng, chương trình này sử dụng 3 hàm trong zlib:
deflateInit_()
: Để bắt đầu néndeflate()
: Để thực hiện thao tác nén trên phân đoạn dữ liệudeflateEnd()
: Để kết thúc quá trình nén và các cấu trúc dữ liệu được phân bổ động tự do
Trong ví dụ thực tế, bạn sẽ xem lại thư viện C/C++ và quyết định hàm nào cần thiết. Một chiến lược khả thi là bắt đầu với Mã máy chủ và sử dụng thư viện không có trong hộp cát. Sau đó, trong bước thứ hai, bạn có thể tạo Thư viện hộp cát và điều chỉnh Mã máy chủ lưu trữ để sử dụng các lệnh gọi hàm trong hộp cát.
2. Viết Quy tắc tạo sapi_library
Sau khi xác định được ba hàm zlib cần thiết từ thư viện zlib trong hộp cát, bạn có thể xác định quy tắc bản dựng trong tệp BUILD. Bạn có thể tìm thấy tài liệu về quy tắc tạo sapi_library
trên trang Quy tắc tạo.
Đoạn mã dưới đây cho thấy định nghĩa sapi_library
cho ví dụ về zlib SAPI. Khi sử dụng thuộc tính lib
, Bazel được hướng dẫn tìm thư viện zlib trong tệp WORKSPACE.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
Kết quả là thư viện zlib hộp cát được tạo. Đầu ra là Đối tượng SAPI có thể đưa vào Mã máy chủ và dùng để giao tiếp với thư viện có hộp cát thông qua lệnh gọi RPC. Chính sách Hộp cát được dùng trong ví dụ này là chính sách mặc định.
3. Viết hoặc thay đổi mã máy chủ
Đã đến lúc kết hợp Thư viện SAPI đã tạo vào Mã máy chủ.
Tạo Hộp cát
Sử dụng sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
để tạo đối tượng hộp cát.
Dùng sapi::zlib::ZlibApi api(&sandbox);
để tạo thực thể cho Đối tượng SAPI, từ đó cung cấp các hàm hộp cát để sử dụng.
Sử dụng các loại SAPI
Loại SAPI là loại đặc biệt dưới dạng lớp C++ mà SAPI cung cấp vì đôi khi loại C thông thường sẽ không hoạt động.
Bạn có thể quan sát lần đầu sử dụng kiểu SAPI trong phần khai báo của strm
, trong đó sử dụng Cấu trúc SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;
Loại mẫu (sapi::zlib::z_stream
) là một ví dụ điển hình về mã do quy tắc tạo tự động.
Hãy xem trang Biến để biết thêm chi tiết.
Thực hiện lệnh gọi API
Để thực hiện lệnh gọi đến defalteInit_
, deflate
hoặc deflateEnd
, hãy sử dụng Đối tượng SAPI. Nếu quyết định sử dụng phương pháp "thay đổi", bạn phải đảm bảo rằng các tham số hàm khớp với các giá trị dự kiến.
Ví dụ về từng lệnh gọi trong ví dụ về 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();
Sử dụng giao dịch SAPI
SAPI tách Mã máy chủ khỏi Thư viện hộp cát và cho phép phương thức gọi có thể khởi động lại hoặc huỷ các yêu cầu xử lý dữ liệu có vấn đề. Giao dịch SAPI tiến thêm một bước và tự động lặp lại các quy trình không thành công.
Hãy xem trang Giao dịch API để biết thêm chi tiết.
Ví dụ
Trong phần Ví dụ, bạn có thể thấy một số thư viện đã được nhóm SAPI chuẩn bị.