Na tej stronie dowiesz się, jak utworzyć własną bibliotekę C/C++ w trybie piaskownicy za pomocą interfejsu Sandboxed API (SAPI). Wykorzystaj go jako przewodnik razem z przykładami i dokumentacją kodu w plikach nagłówka.
Tworzenie zależności
W systemie muszą być zainstalowane te zależności:
- Jądro systemu Linux z obsługą przestrzeni nazw UTS, IPC, użytkownika, PID i sieciowych przestrzeni nazw
- Nagłówki interfejsu Linux Userspace API
- Aby skompilować kod: GCC 6 (preferowana wersja 7 lub nowsza) lub Clang 7 (lub nowsza)
- Automatyczne generowanie plików nagłówka: powiązania Clang Python
- Python 3.5 lub nowszy
- Bazel w wersji 2.2.0 bądź CMake w wersji 3.12 lub nowszej.
Korzystanie z Bazela
Zalecanym systemem kompilacji jest Bazel, który najłatwiej można zintegrować.
W naszej dokumentacji korzystamy z kompilatora Clang. Jeśli potrzebujesz konkretnego łańcucha narzędzi (np. kompilatora lub kreatora linków), zapoznaj się z dokumentacją Baidu, aby dowiedzieć się, jak zmienić domyślny łańcuch narzędzi kompilatora.
Debian 10 (Buster)
Aby zainstalować zależności kompilacji:
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
Gentua
Wymagane opcje jądra:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Aby zainstalować zależności kompilacji:
emerge dev-util/bazel dev-python/typing dev-python/clang-python
Korzystanie z CMake
CMake to popularny system metakompilacji typu open source, który generuje pliki projektów na potrzeby narzędzi do kompilacji, takich jak Ninja czy Make.
Debian 10 (Buster)
Aby zainstalować zależności kompilacji:
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
Gentua
Wymagane opcje jądra:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Aby zainstalować zależności kompilacji:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python
Proces programowania
Aby umieścić bibliotekę C/C++ w piaskownicy, musisz przygotować dwa elementy do swojego projektu:
- Biblioteka w trybie piaskownicy
- Kod hosta, który będzie korzystać z funkcji dostępnych w bibliotece w trybie piaskownicy. Podczas procesu kompilacji SAPI automatycznie wygeneruje obiekt SAPI i kod RPC.
Być może znasz zlib z przykładów piaskownicy2. Cały program (zpipe.c) jest w piaskownicy. Z kolei dowiesz się, jak korzystać z biblioteki w trybie piaskownicy za pomocą interfejsu SAPI i piaskownicy z biblioteki zlib.
1. Określanie, które funkcje są potrzebne
Jeśli spojrzysz na kod hosta zlib (main_zlib.cc), zobaczysz, że jego funkcje to odczytywanie danych z pliku stdin i używanie funkcji deflate()
zlib do skompresowania danych do momentu odczytania znacznika EOF
. Łącznie program wykorzystuje 3 funkcje z zlib:
deflateInit_()
: aby zainicjować w celu kompresjideflate()
: przeprowadza operację kompresji na fragmencie danych.deflateEnd()
: aby zakończyć kompresję i bezpłatne, dynamicznie przydzielane struktury danych
W praktyce warto przejrzeć bibliotekę C/C++ i zdecydować, które funkcje są potrzebne. Można zacząć od kodu hosta i używać biblioteki poza piaskownicą. Następnie można wygenerować Bibliotekę w trybie piaskownicy i dostosować kod hosta tak, aby wykorzystywał wywołania funkcji piaskownicy.
2. Napisz regułę kompilacji sapi_library
Po zidentyfikowaniu 3 funkcji zlib wymaganych w bibliotece zlib w trybie piaskownicy możesz zdefiniować regułę kompilacji w pliku BUILD. Dokumentację reguły kompilacji sapi_library
znajdziesz na stronie Reguły kompilacji.
Fragment kodu poniżej zawiera definicję sapi_library
dla przykładowego interfejsu SAPI zlib. Przy użyciu atrybutu lib
Bazel ma znaleźć bibliotekę zlib w pliku WORKSPACE.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
W efekcie zostanie wygenerowana biblioteka zlib w trybie piaskownicy. Dane wyjściowe to obiekt SAPI, który można umieścić w kodzie hosta i za jego pomocą komunikować się z biblioteką w trybie piaskownicy za pomocą wywołań RPC. Użyta w tym przykładzie zasada piaskownicy jest zasadą domyślną.
3. Zapisywanie lub zmienianie kodu hosta
Teraz należy włączyć wygenerowaną bibliotekę SAPI do kodu hosta.
Utwórz piaskownicę
Użyj polecenia sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
, aby utworzyć obiekt piaskownicy.
Użyj metody sapi::zlib::ZlibApi api(&sandbox);
, aby utworzyć instancję obiektu SAPI i tym samym udostępnić do użycia funkcje piaskownicy.
Używanie typów SAPI
Typy SAPI to specjalne typy klas C++ udostępniane przez SAPI, ponieważ czasami zwykłe typy C nie działają.
Pierwsze użycie typu SAPI można zaobserwować w deklaracji strm
, gdzie używany jest struktura SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;
Typ szablonu (sapi::zlib::z_stream
) jest dobrym przykładem kodu automatycznie generowanego przez regułę kompilacji.
Więcej informacji znajdziesz na stronie Zmienne.
Wykonywanie wywołań interfejsu API
Aby wywoływać metody defalteInit_
, deflate
lub deflateEnd
, użyj obiektu SAPI. Jeśli wybierzesz metodę „zmiany”, musisz upewnić się, że parametry funkcji są zgodne z oczekiwanymi wartościami.
Przykład każdego wywołania w przykładzie 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();
Korzystanie z transakcji SAPI
Interfejs SAPI izoluje kod hosta od biblioteki w trybie piaskownicy i daje elementowi wywołującemu możliwość ponownego uruchamiania lub przerywania problematycznych żądań przetwarzania danych. Transakcja SAPI idzie o krok dalej i automatycznie powtarza nieudane procesy.
Więcej informacji znajdziesz na stronie transakcji SAPI.
Przykłady
W sekcji Przykłady znajdziesz kilka bibliotek przygotowanych przez zespół SAPI.