Nesta página, você vai aprender a criar sua própria biblioteca C/C++ em sandbox com a API Sandboxed (SAPI). Use-a como guia junto com os exemplos e a documentação de código nos arquivos de cabeçalho.
Dependências do build
As seguintes dependências precisam ser instaladas no sistema:
- Kernel do Linux com suporte para namespaces UTS, IPC, de usuário, PID e de rede
- Cabeçalhos da API do espaço do usuário do Linux
- Para compilar o código: GCC 6 (versão 7 ou mais recente recomendada) ou Clang 7 (ou mais recente)
- Para gerar arquivos de cabeçalho automaticamente: vinculações do Python do Clang
- Python 3.5 ou mais recente
- Bazel versão 2.2.0 ou CMake versão 3.12 ou mais recente.
Como usar o Bazel
O Bazel é o sistema de build recomendado e o mais fácil de integrar.
Nossa documentação usa o compilador Clang. Se você precisar de um conjunto de ferramentas específico (por exemplo, compilador, vinculador etc.), consulte a documentação do Bazel para saber como mudar o conjunto de ferramentas do compilador padrão.
Debian 10 (Buster)
Para instalar dependências de build:
echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \ sudo tee /etc/apt/sources.list.d/bazel.listwget -qO - https://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
Opções de kernel necessárias:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Para instalar dependências de build:
emerge dev-util/bazel dev-python/typing dev-python/clang-pythonComo usar o CMake
O CMake é um sistema de meta build de código aberto popular que gera arquivos de projeto para ferramentas de build, como Ninja ou Make.
Debian 10 (Buster)
Para instalar dependências de build:
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
Opções de kernel necessárias:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
Para instalar dependências de build:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-pythonProcesso de desenvolvimento
Para colocar uma biblioteca C/C++ em sandbox, você precisa preparar dois itens para o projeto:
- A biblioteca em sandbox
- O código do host que vai usar a funcionalidade exposta pela biblioteca em sandbox. A SAPI vai gerar o objeto SAPI e o stub RPC automaticamente para você durante o processo de build.
Talvez você já conheça a zlib dos exemplos do Sandbox2 aqui, um programa inteiro (zpipe.c) foi colocado em sandbox. Nas etapas a seguir, você vai aprender a usar a SAPI para colocar a biblioteca zlib em sandbox e usar a biblioteca em sandbox.
1. Decida quais funções são necessárias
Se você analisar o código do host zlib
(main_zlib.cc),
verá que a funcionalidade da ferramenta é ler dados do stdin e usar
a função deflate() da zlib para compactar os dados até que um marcador EOF seja lido.
No total, o programa usa três funções da zlib:
deflateInit_(): para inicializar a compactaçãodeflate(): para executar a operação de compactação no bloco de dadosdeflateEnd(): para encerrar a compactação e liberar estruturas de dados alocadas dinamicamente
Em um exemplo real, você analisaria a biblioteca C/C++ e decidiria quais funções são necessárias. Uma estratégia possível é começar com o código do host e usar a biblioteca sem sandbox. Em seguida, em uma segunda etapa, você pode gerar a biblioteca em sandbox e adaptar o código do host para usar as chamadas de função em sandbox.
2. Escreva a regra de build sapi_library
Depois de identificar as três funções zlib necessárias da
biblioteca zlib em sandbox, você pode definir a regra de build no
arquivo BUILD. A documentação da regra de build sapi_library pode ser encontrada na página
Regras de build.
O snippet de código abaixo mostra a definição sapi_library para o exemplo de SAPI zlib. Usando o lib atributo, o Bazel é instruído a procurar a biblioteca zlib no arquivo
WORKSPACE.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
Como resultado, a biblioteca zlib em sandbox é gerada. A saída é o objeto SAPI, que pode ser incluído no código do host e usado para se comunicar com a biblioteca em sandbox por chamadas RPC. A política de sandbox usada neste exemplo é a padrão.
3. Escreva ou mude o código do host
Agora é hora de incorporar a biblioteca SAPI gerada ao código do host.
Criar o sandbox
Use sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create()); para criar um objeto de sandbox.
Use sapi::zlib::ZlibApi api(&sandbox); para instanciar o objeto SAPI e, assim,
disponibilizar as funções em sandbox para uso.
Usar tipos de SAPI
Os tipos de SAPI são tipos especiais na forma de classes C++ que a SAPI fornece porque, às vezes, os tipos C normais não funcionam.
O primeiro uso de um tipo de SAPI pode ser observado na declaração de strm, em que
uma estrutura SAPI é usada: sapi::v::Struct<sapi::zlib::z_stream> strm;
O tipo de modelo (sapi::zlib::z_stream) é um bom exemplo de código gerado automaticamente pela regra de build.
Consulte a página Variáveis para mais detalhes.
Fazer chamadas de API
Para fazer chamadas para defalteInit_, deflate ou deflateEnd, use o objeto SAPI. Se você decidir usar a abordagem "mudar", verifique se os parâmetros da função correspondem aos valores esperados.
Um exemplo de cada uma das chamadas no exemplo 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();
Como usar transações SAPI
A SAPI isola o código do host da biblioteca em sandbox e oferece ao autor da chamada a capacidade de reiniciar ou anular solicitações problemáticas de processamento de dados. A transação SAPI vai um passo além e repete automaticamente os processos com falha.
Consulte a página Transações SAPIpara mais detalhes.
Exemplos
Em Exemplos, você encontra algumas bibliotecas já preparadas pela equipe da SAPI.