Compartilhar via


Sugestões de design de aplicativos principais de alto nível

Importante

Esta é a documentação do Azure Sphere (herdado). O Azure Sphere (herdado) será desativado em 27 de setembro de 2027 e os usuários devem migrar para o Azure Sphere (integrado) até esse momento. Use o seletor de versão localizado acima do sumário para exibir a documentação do Azure Sphere (Integrado).

Para criar um aplicativo principal de alto nível (HL) em bases sólidas, você deve usar as práticas recomendadas fundamentais. A seguir estão os mais relevantes:

Os aplicativos principais de alto nível (HL) são executados em contêineres no sistema operacional do Azure Sphere. Durante as revisões de código e design das soluções dos clientes, encontramos vários problemas típicos com aplicativos HL-core. Este tópico discute sugestões de melhorias de design para resolver esses problemas.

Fundamentos gerais

Para criar um aplicativo HL-core em bases sólidas, você deve usar as práticas recomendadas fundamentais. A seguir estão os mais relevantes:

  • Inicialização e encerramento: sempre certifique-se de lidar com o sinal SIGTERM do sistema operacional do Azure Sphere e inicialize e destrua corretamente todos os manipuladores (como os de periféricos) na saída, seja em caso de falha ou erro. Para obter mais detalhes, consulte Inicialização e encerramento e a documentação GNU sobre Sinais de Terminação.
  • Sempre use códigos de saída: garantir que o aplicativo HL-core sempre forneça um código de retorno significativo na saída ou falha (por exemplo, usando o manipulador SIGTERM) é essencial para diagnosticar corretamente o comportamento do dispositivo, especialmente da telemetria de despejo de memória do dispositivo. Para obter mais informações, consulte Códigos de saída e Coletar e interpretar dados de erro.
  • Certifique-se de que os casos de falha sempre resultem em uma saída ou falha do aplicativo, em vez de em um estado de deadlock: A lógica elaborada de recuperação de falhas pode ser contraproducente, pois pode introduzir bugs ou comportamentos, resultando em um deadlock ou um estado difícil de diagnosticar. Um aplicativo do Azure Sphere bem projetado sempre deve preferir falhar ou sair (com um código de saída diferente de zero) a uma possível situação de deadlock, pois isso resulta em:
    • Telemetria de erro, habilitando o diagnóstico para esse problema
    • Uma chance de recuperação imediata para um estado de trabalho, pois o sistema operacional do Azure Sphere reiniciará o aplicativo
  • Tratamento de erros e registro: o tratamento preciso de erros e o registro em log estão no centro do desenvolvimento de aplicativos de qualidade. As implementações de funcionalidade rápida podem permanecer enterradas em camadas de código e, em seguida, construídas à medida que o aplicativo se desenvolve até a escala total. Para obter mais informações sobre as práticas recomendadas, consulte Tratamento de erros e registro em log.
  • Use um temporizador do sistema como um watchdog: uma das melhores práticas mais importantes é implementar um retorno de chamada de "temporizador de watchdog" (muito parecido com os de hardware disponíveis em MCUs bare-metal) que rastreia estados críticos do aplicativo, detectando deadlock e agindo de acordo (por exemplo, saindo e enviando telemetria). Para obter mais informações, consulte Usar um temporizador do sistema como um watchdog.
  • Nunca implante aplicativos de produção que foram criados visando um conjunto de ferramentas de versão beta: o uso de conjuntos de ferramentas de versão beta não é recomendado porque não é possível garantir que o subconjunto beta não será alterado nas versões subsequentes do sistema operacional. Os conjuntos de ferramentas beta são lançados exclusivamente para testar novos recursos antes de um lançamento oficial do SDK.

Tratamento de simultaneidade

  • Use EventLoop sempre que possível: threads e objetos de sincronização (ou seja, mutexes, semáforos e assim por diante) são usados para realizar tarefas quase simultâneas, mas em sistemas embarcados eles são caros em termos de uso de recursos do sistema. Portanto, para melhorar o desempenho, considere o uso de epolls em vez de threads, para as tarefas que não são estritamente críticas em termos de tempo e não são sensíveis ao bloqueio mútuo. Consulte Applibs eventloop.h para obter informações sobre como monitorar e despachar eventos com EventLoop, incluindo exemplos relacionados.
  • Procure eficiência em tarefas simultâneas: é importante garantir que as operações de bloqueio e os tempos limite sejam mantidos no mínimo nos retornos de chamada do epoll, caso contrário, todos os outros retornos de chamada do epoll serão afetados.
  • Quando usar threads (pthread): para cenários específicos, como quando o bloqueio de chamadas é inevitável, o uso de threads pode ser benéfico, embora normalmente esses cenários tenham um tempo de vida limitado e devam ter como escopo tarefas específicas. Por exemplo, dado que o sistema operacional do Azure Sphere (executando o Linux) não expõe IRQs a aplicativos HL-core (isso está disponível apenas para aplicativos RT-core), o uso de uma combinação de tarefas epoll e pthread pode ser ideal para lidar, por exemplo, com uma comunicação serial downstream durante o download de dados da Internet.

Importante

O sistema operacional do Azure Sphere pode interromper operações oportunas, especialmente quando está executando o atestado do dispositivo, verificando se há atualizações ou carregando telemetria. Para tarefas de controle de tempo crítico, considere movê-las para os núcleos M4 e coordená-las com um protocolo apropriado por meio da caixa de correio entre núcleos. Para obter mais informações, consulte o exemplo de comunicação entre núcleos.

Além dessas sugestões, examine a documentação do Azure Sphere sobre eventos assíncronos e simultaneidade.

Monitoramento de conectividade

Um aplicativo principal HL (alto nível) bem projetado deve implementar uma tarefa adequada de Verificação de Integridade de Conectividade , que deve ser baseada em uma máquina de estado robusta que verifica regularmente o status da conexão com a Internet (por exemplo, usando um temporizador epoll ) aproveitando a API Networking_IsNetworkingReady . Em alguns casos, você pode usar a função Networking_GetInterfaceConnectionStatus, pois ela fornece um status mais aprofundado do estado de conectividade relacionado a uma interface de rede específica que o aplicativo HL-core pode usar para lidar melhor com seu estado, embora isso tenha um custo, pois não é recomendável chamá-lo com mais frequência do que a cada 90 segundos.

O retorno de chamada da máquina de estado normalmente deve ter os seguintes atributos:

  • Execute o mais rápido possível.
  • Seu intervalo de sondagem deve ser cuidadosamente projetado, com base no cenário de aplicativo específico e nos requisitos gerais da solução (como tempo constante, atraso incremental e assim por diante).
  • Depois que uma desconexão é detectada, pode ser útil chamá Networking_GetInterfaceConnectionStatus uma vez para registrar o estado da interface de rede específica, que pode ser usada para diagnosticar o problema e notificar o usuário por meio de uma interface do usuário (como LEDs, display, terminal). Um exemplo dessa abordagem pode ser encontrado no código principal do Exemplo de DHCP do Azure Sphere.
  • Ative um mecanismo (por exemplo, por meio de uma variável global) que interrompa todas as outras tarefas no aplicativo HL-core que executam (ou estão vinculadas a) comunicações de rede para otimizar o consumo de recursos até que uma conexão seja restabelecida.
  • O cURL atualizou recentemente o comportamento de retorno de chamada e as práticas recomendadas. Embora o Azure Sphere tenha se esforçado para garantir que as versões mais antigas do comportamento cURL continuem funcionando conforme o esperado, é recomendável seguir as diretrizes mais recentes de segurança e confiabilidade ao usar o curl_multi, pois o uso de retornos de chamada recursivos pode resultar em falhas inesperadas, interrupções de conectividade e possíveis vulnerabilidades de segurança. Se um TimerCallback for acionado com um tempo limite de 0ms, trate-o como um tempo limite de 1ms para evitar retornos de chamada recursivos. Certifique-se também de chamar curl_multi_socket_action explicitamente pelo menos uma vez após chamadas para curl_multi_add_handle.

Além das sugestões anteriores, você deve considerar os seguintes cenários para gerenciamento de energia:

  • Desligue o chip do Azure Sphere após o envio de dados. Para obter detalhes, consulte Gerenciar o estado de desligamento para dispositivos do Azure Sphere.
  • Como vários problemas podem resultar de longos tempos limite de recuo exponencial, é fundamental rastrear o tempo de atividade total e definir um temporizador de desligamento para um limite razoável para não esgotar a bateria em condições em que a conectividade não é mais possível devido a interrupções externas ou outros fatores além do controle do aplicativo.
  • Ao controlar o monitoramento de conectividade durante interrupções, o transceptor Wi-Fi pode desligar desativando a interface de rede (consulte Networking_SetInterfaceStatewlan0) e aguardando até a próxima verificação de conectividade novamente, economizando aproximadamente 100 mW.

Gerenciamento e uso de memória

Em plataformas com restrição de memória, os aplicativos que executam alocações e desalocações frequentes de memória podem fazer com que o gerenciamento de memória do sistema operacional tenha dificuldades com a eficiência, causando fragmentação excessiva e esgotamento da memória. Especificamente no Azure Sphere MT3620, isso pode levar a condições de falta de memória que podem disparar o assassino OOM cgroup do sistema operacional do Azure Sphere para iniciar.

Compreensivelmente, os aplicativos geralmente são desenvolvidos a partir de uma prova de conceito inicial, que se torna mais abrangente com os recursos necessários para versões progressivas, eventualmente negligenciando recursos menores que foram inicialmente incluídos. A seguir estão sugestões e otimizações que se mostraram eficazes para muitos cenários analisados em campo:

  • Especialmente em aplicativos HL-core que fazem uso intensivo de memória, é essencial acompanhar o uso de memória do aplicativo por meio da API do Azure Sphere, descrita em Determinar o uso de RAM do aplicativo em tempo de execução. Normalmente, isso é implementado em um watchdog de temporizador de pesquisa eletrônica e o aplicativo reage de acordo com o uso inesperado de memória para reiniciar de maneira razoável; por exemplo, sair com o código de saída apropriado.

    Vários clientes e parceiros acharam útil usar o utilitário de acompanhamento de memória do Rastreador de Heap, que é publicado na Galeria do Azure Sphere. Essa biblioteca se vincula de forma transparente a um aplicativo HL-core existente e rastreia as alocações de memória e seus ponteiros relacionados, permitindo a detecção simplificada da maioria dos casos de vazamentos de memória e usos indevidos de ponteiro.

Importante

Essa prática pode reduzir a falta de resposta do dispositivo aparentemente inexplicável ou falhas frequentemente relatadas em campo. Essas falhas geralmente são causadas por vazamentos de memória ou saturações que não são tratadas adequadamente pelo aplicativo HL-core e levam o assassino OOM a desligar o processo do aplicativo. Isso, juntamente com a conectividade ruim que impede que o sistema operacional do Azure Sphere envie telemetria, pode levar a possíveis incidentes de campo, pois o diagnóstico só pode ser detectado extraindo os logs de diagnóstico do sistema operacional do Azure Sphere.

  • Em plataformas com restrição de memória, geralmente é preferível evitar a alocação dinâmica de memória sempre que possível, especialmente em funções chamadas com frequência. Isso reduzirá bastante a fragmentação de memória do heap e a probabilidade de falhas subsequentes de alocação de heap. Considere também uma mudança de paradigma da alocação repetitiva de buffers de trabalho temporários para acessar diretamente a pilha (para variáveis de tamanhos razoáveis) ou buffers alocados globalmente, que aumentam de tamanho (por meio reallocde ) após o estouro (consulte Contêineres e buffers dinâmicos). Se houver um requisito para descarregar memória, considere aproveitar a memória não utilizada nos núcleos M4 (consulte Memória disponível no Azure Sphere), que têm 256 KiB cada, com um aplicativo RT-core leve para cache de dados. Você pode eventualmente usar cartões SD externos ou flash. As amostras podem ser encontradas nos seguintes repositórios:

Seguir as sugestões acima também pode ajudar a estimar e reservar a memória que seria necessária para que o aplicativo HL-core funcione em plena capacidade em todo o seu ciclo de vida, permitindo estimar melhor o volume de memória geral do aplicativo para otimizações de design posteriores. Para obter mais informações sobre como otimizar o uso de memória em aplicativos HL-core, incluindo recursos no sistema operacional do Azure Sphere e no Visual Studio, consulte os seguintes artigos: