Biblioteca subjacente de plataforma cruzada https://github.com/hujianzhe/util, baixe e coloque-a no diretório BootServer
Introdução:
O código implementa apenas inicialização de inicialização do nó de serviço, agendamento de tarefas e descrição básica do módulo. Ele não contém nenhum código de negócios. Ele é implementado em C puro. Geralmente é compilado em uma biblioteca dinâmica e permanece extremamente restrito em termos de funções de uso. Ele implementa alguns fluxos de protocolo comuns e suporta extensão C++ 20 de corrotina sem pilha e isolada de alguns códigos da biblioteca dinâmica C pura para evitar que C++ contamine a camada da estrutura e afete a geração da biblioteca dinâmica.
O código no util é responsável pela plataforma cruzada, exceto que não requer a instalação de nenhuma biblioteca de terceiros
Introdução ao processo de operação:
O processo de negócios chama a biblioteca dinâmica compilada pelo código e chama a interface correspondente para uso. Para obter detalhes sobre o processo de chamada, consulte o exemplo do nó de teste (main_template no diretório BootServer é um conjunto de modelos de código de inicialização baseados em processo).
Vários threads lidam com leitura e gravação de E/S de rede dentro do módulo. Um thread de acesso de aceitação separado abrirá inicialmente um thread de trabalho para processar mensagens internas e mensagens de rede recebidas e enviá-las para sua lógica de código de negócios. O thread de trabalho usa uma corrotina de pilha para agendar o processamento (veja abaixo o motivo pelo qual uma corrotina sem pilha não é usada)
Threads de trabalho usam corrotinas de pilha para agendamento por padrão para manter a compatibilidade mais alta. Você também pode usar corrotinas sem pilha C++20 (uma implementada na biblioteca de utilitários) para agendamento.
Introdução do módulo e código de exemplo:
1. BootServer: parte do código principal, inicialização necessária e operação dos nós de serviço
2. ServiceTemplate: modelo de código do nó de serviço, usado para escrever sua lógica de negócios
3. SoTestClient, SoTestServer: testou nós e escreveu alguns códigos de amostra
4. Cpp20-SoTestServer: nó de teste, escreveu alguns códigos de amostra, habilitou a corrotina sem pilha C++20 em main.cpp (usando um agendador de corrotina sem pilha C++20 na biblioteca de utilitários)
Compilar:
compilação direta do Windows VS
Use make debug / make release / make asan no Linux/Mac OS X
comece:
Edite o arquivo de configuração necessário para a inicialização do nó de serviço (consulte o modelo de arquivo de configuração anexado para obter o formato específico) e forneça a cada nó um arquivo de configuração e um ID exclusivo, nome de identificação de log, IP e número de porta.
O Windows abre diretamente no VS e o projeto é configurado com parâmetros de inicialização <arquivo de configuração>
Após a compilação do linux/mac, sh run.sh <processo de serviço> <arquivo de configuração>
Algumas razões e insights de design: P: Por que não usar corrotinas sem pilha, mas sim corrotinas empilhadas? R: É fácil implementar corrotinas sem pilha em C puro (para código detalhado, você pode ver o agendador de corrotinas sem pilha implementado em C puro na biblioteca de utilitários), mas reciclagem de recursos e persistência (especialmente variáveis na pilha estão sujeitas a re-rotinas). -entrada). (a última situação) é extremamente difícil. Se você quiser usar corrotinas sem pilha sem problemas, ainda precisará contar com o suporte do compilador. Isso foi alcançado no C++20. Há também uma implementação completa do agendador de corrotinas sem pilha do C++20 na biblioteca de utilitários.
P: Por que a corrotina sem pilha fornece essa função estendida na forma de um arquivo de cabeçalho?
R: 1. Porque as corrotinas sem pilha são intrusivas no código e alterarão um grande número de formulários de assinatura de função
2. Contém objetos C++, que não são reconhecidos em C, e a biblioteca dinâmica não pode ser exportada com êxito.
3. Dado na forma de um arquivo de cabeçalho, entregar a permissão de ativação de corrotinas sem pilha para a camada de aplicativo é a maneira que penso atualmente para lidar com a parte da biblioteca dinâmica C pura sem qualquer poluição.
P: Ele pode ser substituído por outros agendadores?
R: O agendador do thread de trabalho pode ser substituído. O thread de trabalho é projetado como a transportadora em execução do agendador. A interação entre o thread de rede e o thread de trabalho dentro da estrutura pode corresponder ao comportamento de agendamento por meio do gancho de interface.
P: Ela pode ser substituída por outras bibliotecas de rede?
R: 1. Atualmente, ela não pode ser substituída por outras bibliotecas de rede, mas esta questão foi considerada no início do projeto. A parte de rede e a parte de agendamento de tarefas serão completamente separadas no futuro, e os comportamentos correspondentes serão semelhantes ao thread de trabalho. ganchos serão fornecidos para substituição.
2. Embora existam muitas bibliotecas de rede de terceiros, seus focos são diferentes. Existem bibliotecas TCP e UDP utilizadas para desenvolvimento de aplicações, existem também bibliotecas que desejam incluir todo o universo, e também existem bibliotecas que implementam toda a pilha de protocolos de rede na camada de aplicação, portanto na verdade esta área não é unificada.
3. Se um conjunto de bibliotecas de rede entrar no padrão no futuro, irei substituí-lo.
P: Por que não usar C++ apenas como estrutura?
R: 1. Quando este conjunto de código foi escrito, o C++20 ainda não havia aparecido. Naquela época, a solução de corrotina relativamente mais madura era a corrotina de pilha. Isso poderia ser feito usando C chamando a API do sistema da plataforma correspondente.
2. As funções a serem implementadas por este tipo de framework foram solidificadas, e o ciclo de vida dos recursos é solidificado pelo processo. Basta implementá-lo em C puro (antes havia uma versão implementada em C++, e a. o código era mais complicado)
3. Se a biblioteca dinâmica for chamada por outros módulos, ela ainda precisará selar uma interface em C
4. As classes exportadas em C++ são contagiosas e a ABI não é unificada
P: A camada de negócios pode continuar a ser desenvolvida usando C puro?
R: Não é altamente recomendado, porque a gravação de processos assíncronos e exceções lançadas em módulos escritos em linguagens de alto nível tornam incerto o momento da destruição de recursos. Neste momento, é extremamente difícil controlar manualmente os recursos usando C puro. Você deve usar uma linguagem de nível superior para lidar com essas coisas. Por exemplo, você pode usar C++ para desenvolver código de negócios de nível superior e seu mecanismo RAII pode garantir a liberação dos recursos correspondentes.
P: Se eu quiser transformar o "retorno de chamada" do projeto antigo em uma "rotina", posso simplesmente substituir a parte do agendador pelo ponto de chamada correspondente no código comercial?
R: Não é tão simples. A primeira é a questão da carga de trabalho. Além disso, seja na forma de retorno de chamada ou na forma de rotina, a essência é emitir uma solicitação e aguardar o resultado. é um problema que deve ser resolvido e deve ser cuidadosamente considerado. Se for um ponteiro Raw, então quase se pode dizer que não pode ser transformado se o projeto tiver utilizado. Meios como std::shared_ptr prolongam o ciclo de vida das variáveis, por isso será menos difícil transformá-las em uma versão de "co-rotina de pilha". Se você quiser transformar em uma corrotina sem pilha C++20, a carga de trabalho é enorme. equivale a reescrever o projeto (porque corrotinas sem pilha têm forte intrusão de código), portanto é recomendado não transformar projetos antigos.
P: Por que atualmente a corrotina não pode ser migrada para threads diferentes para execução?
R: A migração de corrotinas pode ser feita facilmente, mas o motivo pelo qual ela não é fornecida é
1. As tarefas executadas entre corrotinas são incertas, o que pode fazer com que io e cálculo sejam misturados no mesmo thread de agendamento.
2. Após a migração, o mesmo processo de corrotina pode ser executado em threads diferentes. Nesse caso, você deve garantir que seu código não dependa de nenhuma variável local de thread, mas não pode garantir que a biblioteca de terceiros não use variáveis locais de thread. .
P: O asan travará durante a compilação e execução?
R: 1. Se você estiver usando a corrotina empilhada padrão da estrutura, definitivamente não é um problema de código. Você pode ajustar o tamanho da pilha da corrotina empilhada no arquivo de configuração do nó (quando o ASAN estiver habilitado, um espaço de pilha relativamente grande será consumido, então existe a possibilidade de explosão da pilha)
2. ASAN não suporta totalmente a API de corrotina empilhada (ucontext) no ambiente Unix Embora a API de corrotina ucontext tenha sido adaptada para ASAN no código utilitário, ela ainda não pode garantir 100% que não haverá problemas de execução no ASAN. ambiente (até agora tudo bem)
3. Em algumas distribuições Linux mais recentes, se o ASAN gerar AddressSanitizer: DEADLYSIGNAL infinitamente, ajuste sudo sysctl vm.mmap_rnd_bits=28 para resolver o problema.
PENDÊNCIA:
1. Realmente não tenho tempo para escrever uma documentação detalhada.
2. Fornece suporte para escrever lógica de negócios em linguagem de script