Sugestões de design de aplicativos principais de alto nível
Importante
Esta é a documentação do Azure Sphere (Legado). O Azure Sphere (Legado) 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 práticas recomendadas fundamentais. São os mais relevantes:
Os aplicativos principais de alto nível (HL) são executados em contêineres no sistema operacional 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 sobre bases sólidas, você deve usar práticas recomendadas fundamentais. São os mais relevantes:
- Inicialização e encerramento: sempre certifique-se de manipular o sinal SIGTERM do sistema operacional Azure Sphere e inicializar e destruir corretamente todos os manipuladores (como os de periféricos) ao sair, seja em caso de falha ou erro. Para obter mais detalhes, consulte Inicialização e terminação e a documentação do GNU sobre sinais de terminação.
- Use sempre códigos de saída: Certificar-se de que o aplicativo HL-core sempre forneça um código de retorno significativo ao sair ou falhar (por exemplo, usando o manipulador SIGTERM) é essencial para diagnosticar corretamente o comportamento do dispositivo, especialmente a partir da telemetria de despejo de falha 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 impasse: a lógica de recuperação de falha elaborada pode ser contraproducente, pois pode introduzir bugs ou comportamentos que resultam em um deadlock ou um estado difícil de diagnosticar. Um aplicativo do Azure Sphere bem projetado sempre deve preferir travar ou sair (com um código de saída diferente de zero) a uma possível situação de impasse, pois isso resulta em:
- Telemetria de erro, habilitando diagnósticos para esse problema
- Uma chance de recuperação imediata para um estado de trabalho, já que o sistema operacional Azure Sphere reiniciará o aplicativo
- Tratamento e registro de erros: 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 práticas recomendadas, consulte Tratamento e registro de erros.
- Use um temporizador do sistema como um cão de guarda: Uma das melhores práticas mais cruciais é implementar um retorno de chamada de "temporizador de vigilância" (muito parecido com os de hardware disponíveis em MCUs bare-metal) que rastreia estados críticos de aplicativos, detetando deadlock e agindo de acordo (por exemplo, saindo e enviando telemetria). Para obter mais informações, consulte Usar um temporizador do sistema como um cão de guarda.
- Nunca implante aplicativos de produção que tenham sido 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.
Manipulação de simultaneidade
- Use o 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 aquelas 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 enviar eventos com o 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 a um mínimo dentro dos retornos de chamada da epoll, caso contrário, todos os outros retornos de chamada da 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 escopo para tarefas específicas. Por exemplo, dado que o sistema operacional Azure Sphere (executando Linux) não expõe IRQs a aplicativos HL-core (isso está disponível apenas para aplicativos RT-core), usar 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 Azure Sphere pode interromper operações oportunas, especialmente quando está executando atestado de dispositivo, verificando atualizações ou carregando telemetria. Para tarefas de controle de tempo crítico, considere movê-los para os núcleos M4 e coordená-los 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, consulte a documentação do Azure Sphere sobre eventos assíncronos e simultaneidade.
Monitoramento de conectividade
Um aplicativo principal de alto nível (HL) bem projetado deve implementar uma tarefa adequada de Verificação de Integridade da 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 detalhado do estado de conectividade relacionado a uma interface de rede específica que o aplicativo HL-core pode usar para abordar melhor seu estado, embora isso tenha um custo, pois não é recomendado 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 específico do aplicativo e nos requisitos gerais da solução (como tempo constante, atraso incremental e assim por diante).
- Uma vez que uma desconexão é detetada, pode ser útil chamar Networking_GetInterfaceConnectionStatus uma vez para registrar o estado da interface de rede específica, que pode ser usado para diagnosticar o problema e notificar o usuário através 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 e as práticas recomendadas de retorno de chamada. Embora o Azure Sphere tenha feito esforços para garantir que versões mais antigas do comportamento cURL continuem a funcionar conforme o esperado, é recomendável seguir as orientações mais recentes de segurança e confiabilidade ao usar 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 ligar para curl_multi_socket_action explicitamente pelo menos uma vez após as chamadas para curl_multi_add_handle.
Além das sugestões anteriores, você deve considerar os seguintes cenários para o gerenciamento de energia:
- Desligue o chip do Azure Sphere depois de enviar 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 exponenciais de back-off, é fundamental rastrear o tempo de atividade total e definir um temporizador de desligamento para um limite razoável para não drenar a bateria em condições onde a conectividade não é mais possível devido a interrupções externas ou outros fatores fora 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_SetInterfaceState
wlan0
) e aguardando até a próxima verificação de conectividade novamente, economizando aproximadamente 100mW.
Gerenciamento e uso de memória
Em plataformas com restrição de memória, os aplicativos que executam alocações e desalocações de memória frequentes 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 acionar o assassino cgroup OOM do sistema operacional Azure Sphere para iniciar.
Compreensivelmente, as aplicações são muitas vezes desenvolvidas a partir de uma prova de conceito inicial, que se torna mais abrangente com 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 controlar o uso da memória do aplicativo por meio da API do Azure Sphere, descrita em Determinar o uso da RAM do aplicativo em tempo de execução. Normalmente, isso é implementado em um watchdog epoll-timer 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 rastreamento de memória Heap Tracker, que é publicado na Galeria do Azure Sphere. Esta biblioteca vincula-se de forma transparente a um aplicativo HL-core existente e rastreia alocações de memória e seus ponteiros relacionados, permitindo a deteçã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 aparentemente inexplicável do dispositivo ou falhas frequentemente relatadas em campo. Tais falhas geralmente são causadas por vazamentos de memória ou saturações que não são tratadas corretamente pelo aplicativo HL-core e levam o assassino OOM a desligar o processo do aplicativo. Isso, juntamente com a conectividade deficiente que bloqueia o sistema operacional Azure Sphere de enviar telemetria, pode levar a possíveis incidentes de campo, já que o diagnóstico só pode ser detetado extraindo os logs de diagnóstico do sistema operacional Azure Sphere.
- Em plataformas com restrição de memória, geralmente é preferível evitar a alocação de memória dinâmica sempre que possível, especialmente em funções frequentemente chamadas. Isso reduzirá significativamente a fragmentação da memória da pilha e a probabilidade de falhas subsequentes de alocação da pilha. Considere também uma mudança de paradigma da alocação repetitiva de buffers de trabalho temporários para o acesso direto à pilha (para variáveis de tamanhos razoáveis) ou buffers alocados globalmente, que aumentam de tamanho (através
realloc
) 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:
Projeto de disco remoto de sistema de arquivos simples
Nota
Os exemplos acima não implementam criptografia, que deve ser levada em consideração dependendo do tipo de dados que você armazenará externamente.
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 que você estime melhor a pegada de memória geral do aplicativo para otimizações de projeto posteriores. Para obter mais informações sobre como otimizar o uso de memória em aplicativos HL-core, incluindo recursos no sistema operacional Azure Sphere e Visual Studio, consulte os seguintes artigos: