Bắt đầu sử dụng Sandboxed API

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.
    • Chỉ CMake: GNU Make hoặc một phiên bản của tiêu đề thư viện libcap và một công cụ xây dựng như Ninja (nên dùng).

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:

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én
  • deflate(): Để thực hiện thao tác nén trên phân đoạn dữ liệu
  • deflateEnd(): Để 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ị.