Cette page explique comment créer votre propre bibliothèque C/C++ en bac à sable avec l'API en bac à sable (SAPI). Utilisez-la comme guide, en complément des exemples et de la documentation du code dans les fichiers d'en-tête.
Créer des dépendances
Les dépendances suivantes doivent être installées sur le système :
- Noyau Linux compatible avec les espaces de noms UTS, IPC, utilisateur, PID et réseau
- En-têtes de l'API de l'espace utilisateur Linux
- Pour compiler votre code : GCC 6 (version 7 ou ultérieure de préférence) ou Clang 7 (ou version ultérieure)
- Pour générer automatiquement des fichiers d'en-tête : liaisons Python Clang
- Python 3.5 ou version ultérieure
- Bazel version 2.2.0 ou CMake version 3.12 ou ultérieure.
Utiliser Bazel
Bazel est le système de compilation recommandé et le plus facile à intégrer.
Notre documentation utilise le compilateur Clang. Si vous avez besoin d'une chaîne d'outils spécifique (compilateur, éditeur de liens, etc.), consultez la documentation Bazel pour savoir comment modifier la chaîne d'outils du compilateur par défaut.
Debian 10 (Buster)
Pour installer les dépendances de compilation :
echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \ sudo tee /etc/apt/sources.list.d/bazel.listwget -qO - https://releases.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
Gentoo
Options de noyau requises :
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Pour installer les dépendances de compilation :
emerge dev-util/bazel dev-python/typing dev-python/clang-pythonUtiliser CMake
CMake est un système de méta-compilation Open Source populaire qui génère des fichiers de projet pour des outils de compilation tels que Ninja ou Make.
Debian 10 (Buster)
Pour installer les dépendances de compilation :
sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \ python3 python3-pip libclang-dev libcap-devpip3 install absl-py clang
Gentoo
Options de noyau requises :
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Pour installer les dépendances de compilation :
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-pythonProcessus de développement
Pour mettre en bac à sable une bibliothèque C/C++, vous devez préparer deux éléments pour votre projet :
- La bibliothèque en bac à sable
- Le code hôte qui utilisera les fonctionnalités exposées par votre bibliothèque en bac à sable. SAPI générera automatiquement l'objet SAPI et le stub RPC pour vous lors du processus de compilation.
Vous connaissez peut-être zlib grâce aux exemples Sandbox2 où un programme complet (zpipe.c) a été mis en bac à sable. Dans les étapes suivantes, vous apprendrez à utiliser SAPI pour mettre en bac à sable la bibliothèque zlib et à utiliser la bibliothèque en bac à sable.
1. Déterminer les fonctions nécessaires
Si vous examinez le code hôte zlib
(main_zlib.cc),
vous pouvez constater que la fonctionnalité de l'outil consiste à lire les données à partir de stdin et à utiliser
la fonction deflate() de zlib pour compresser les données jusqu'à ce qu'un marqueur EOF soit lu.
Au total, le programme utilise trois fonctions de zlib :
deflateInit_(): pour initialiser la compressiondeflate(): pour effectuer l'opération de compression sur le bloc de donnéesdeflateEnd(): pour mettre fin à la compression et libérer les structures de données allouées dynamiquement
Dans un exemple concret, vous examinerez la bibliothèque C/C++ et déterminerez les fonctions nécessaires. Une stratégie possible consiste à commencer par le code hôte et à utiliser la bibliothèque sans bac à sable. Ensuite, dans une deuxième étape, vous pouvez générer la bibliothèque en bac à sable et adapter le code hôte pour utiliser les appels de fonction en bac à sable.
2. Écrire la règle de compilation sapi_library
Une fois que vous avez identifié les trois fonctions zlib nécessaires à partir de la
bibliothèque zlib en bac à sable, vous pouvez définir la règle de compilation dans le
fichier BUILD. La documentation de la règle de compilation sapi_library est disponible sur la page
Règles de compilation.
L'extrait de code ci-dessous montre la définition sapi_library pour l'exemple SAPI zlib. À l'aide de l'attribut lib, Bazel est invité à rechercher la bibliothèque zlib dans le
fichier WORKSPACE.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
La bibliothèque zlib en bac à sable est alors générée. La sortie est l'objet SAPI qui peut être inclus dans le code hôte et utilisé pour communiquer avec la bibliothèque en bac à sable à l'aide d'appels RPC.
Cet exemple utilise la configuration de bac à sable par défaut fournie par
DefaultConfig
(sapi::SandboxConfig::DefaultConfig()).
3. Écrire ou modifier le code hôte
Il est maintenant temps d'intégrer la bibliothèque SAPI générée dans le code hôte.
Créer le bac à sable
Utilisez sapi::zlib::ZlibSandbox sandbox; pour créer un objet de bac à sable.
Utilisez sapi::zlib::ZlibApi api(&sandbox); pour instancier l'objet SAPI et ainsi
rendre les fonctions en bac à sable disponibles.
Pour personnaliser la stratégie, les flags, les variables d'environnement ou les limites du bac à sable, commencez
par sapi::SandboxConfig::DefaultConfig(), modifiez les champs pertinents (à l'aide de
sapi::Sandbox2Config::DefaultPolicyBuilder(),
sapi::SandboxConfig::DefaultFlags(), ou
sapi::SandboxConfig::DefaultEnvironmentVariables() afin de conserver les paramètres de référence), puis transmettez le sapi::SandboxConfig au constructeur du bac à sable :
sapi::SandboxConfig config = sapi::SandboxConfig::DefaultConfig();
config.sandbox2.policy = sapi::Sandbox2Config::DefaultPolicyBuilder()
.AddFile("/path/to/file")
.BuildOrDie();
auto flags = sapi::SandboxConfig::DefaultFlags();
flags["my_flag"] = "value";
config.command_line_flags = std::move(flags);
sapi::zlib::ZlibSandbox sandbox(std::move(config));
Utiliser les types SAPI
Les types SAPI sont des types spéciaux sous la forme de classes C++ que SAPI fournit, car parfois les types C standards ne fonctionnent pas.
La première utilisation d'un type SAPI peut être observée dans la déclaration de strm, où
une structure SAPI est utilisée : sapi::v::Struct<sapi::zlib::z_stream> strm;
Le type de modèle (sapi::zlib::z_stream) est un bon exemple de code généré automatiquement par la règle de compilation.
Pour en savoir plus, consultez la page Variables.
Effectuer des appels d'API
Pour effectuer des appels à defalteInit_, deflate ou deflateEnd, utilisez l'objet SAPI. Si vous décidez d'utiliser l'approche "modifier", vous devez vous assurer que les paramètres de la fonction correspondent aux valeurs attendues.
Voici un exemple de chacun des appels dans l'exemple 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();
Utiliser les transactions SAPI
SAPI isole le code hôte de la bibliothèque en bac à sable et permet à l'appelant de redémarrer ou d'abandonner les requêtes de traitement de données problématiques. La transaction SAPI va encore plus loin et répète automatiquement les processus ayant échoué.
Pour en savoir plus, consultez la page Transactions SAPI.
Exemples
Sous "Exemples", vous trouverez quelques bibliothèques déjà préparées par l'équipe SAPI.