FAVORITAR
FecharPlease login

Desenvolvendo Resource Managers no QNX – Um Guia Prático

Introdução

Em sistemas operacionais tradicionais, o gerenciamento de recursos do hardware é normalmente realizado pelo seu núcleo (kernel) que fica responsável pela gestão da memória, processos e dispositivos. Neste contexto, os device drivers incorporados desempenham a função de intermediários na comunicação com os diversos dispositivos permitindo que os programas interajam com eles de forma eficiente fornecendo uma abstração. 

No sistema operacional QNX, no entanto, estas funcionalidades são implementadas em processos separados do núcleo através dos Resource Managers (gerenciadores de recursos).

Na arquitetura microkernel do sistema operacional QNX o núcleo é estruturado para oferecer apenas os serviços essenciais para todos os demais processos do sistema. A filosofia aqui é torna-lo modular e escalável.

Novos serviços e funcionalidades podem ser adicionados sem a necessidade de alterações no núcleo do sistema, o que simplifica o processo de desenvolvimento, depuração e manutenção. 

No dia 25 de Junho de 2024, ocorrerá o “Seminário de Sistemas Embarcados e IoT 2024“, no Holiday Inn Anhembi — Parque Anhembi, São Paulo–SP.

Garanta seu ingresso

Resource Managers são projetados para fornecer uma interface consistente, segura e abstrata para que os processos possam acessar e manipular recursos específicos do sistema (como dispositivos de hardware e sistemas de arquivos) através da implementação de operações POSIX padrão, de abertura, fechamento, leitura e escrita.

Um gerenciador de recursos no QNX é simplesmente um programa separado do núcleo com algumas características bem definidas.

Quais são as vantagens? 

A API de comunicação dos programas com os Resource Managers no QNX é em sua maioria POSIX via funções open(), read(), write() e close() bem conhecidas.

Suponha que você deseja comunicar-se com um sensor de temperatura instalado em sua placa (target) cujo resource manager já registrou este dispositivo no nome de caminho “/dev/sensors/temperature”. Basta escrever um simples programa em C como mostrado a seguir para obter o valor atual da temperatura deste sensor.

Também é possível comunicar-se com os gerenciadores de recursos via utilitários de linha de comando. Considere a facilidade de obter os dados de um GNSS que foi registrado em /dev/gps e então usar no shell algo assim:

Obtendo logo em seguida:

Com a mesma facilidade, é possível enviar mensagens para os dispositivos via linha de comando. Imagine que você queira alterar a posição de um servo. Basta digitar no terminal e o gerenciador de recursos ficará responsável por receber a mensagem, trata-la e comunicar-se com este dispositivo.

Cada Resource Manager pode ficar responsável por um recurso específico (periféricos, sistema de arquivos, dispositivos de hardware, etc.), oferecendo algum determinado serviço de forma abstrata, ou seja, a aplicação não precisa conhecer nenhum detalhe do funcionamento do periférico ou dispositivo. Basta o uso de chamadas de função POSIX para interagir com eles.

Um robusto sistema de comunicação entre processos (IPC) é responsável pela “tradução” das funções POSIX em mensagens que são construídas e então enviadas diretamente aos gerenciadores de recursos.

Estrutura de um Resource Manager

Um resource manager possui uma estrutura relativamente simples e bem definida da seguinte forma de acordo com a documentação do QNX.

  1. Canal de Conexão (channel):

Um canal de comunicação é criado para que outros programas (clientes) possam se conectar a ele e então enviar e receber mensagens.

  1. Nome do Caminho (pathname):

Um nome de caminho é registrado no gerenciador de processos (Process Manager) informando que o Resource Manager será responsável por lidar com solicitações de clientes para esses nomes de caminho.

  1. Loop de Processamento de Mensagens:

O Resource Manager permanece em um loop contínuo recebendo e processando mensagens, executando alguma ação apropriada com base no seu conteúdo.

Desenvolvimento de um Resource Manager simples

A seguir vamos demostrar o desenvolvimento de um gerenciador de recursos, destacando apenas trechos de código com os principais pontos de design, implementação de funcionalidades essenciais e boas práticas.

As funções, macros e estruturas contidas na biblioteca do gerenciador de recursos torna esta tarefa bastante fácil. Sem ela, provavelmente centenas de linhas de código seriam necessárias para realizar o mesmo trabalho.

Interface de despacho (dispatch interface)

Dispatch Interface é o mecanismo que o gerenciador de recursos utiliza para receber mensagens dos clientes. As funções dispatch_create_channel() e dispatch_create() alocam e inicializam uma estrutura de despacho e retornam um identificador para ela (ou NULL) para o caso de falha.

Atributos do gerenciador de recursos

A estrutura de controle (resmgr_attr_t) contém atributos do gerenciador de recursos que precisam ser inicializado antes de ser passada mais tarde para a função resmgr_attach(). 

Aqui estamos configurando quantas estruturas IOV estão disponíveis para respostas (nparts_max) e também o tamanho do buffer de recepção (msg_max_size).

Estruturas usadas para lidar com as mensagens

Agora vamos indicar as funções que vão ser invocadas quando o gerenciador de recursos receber e identificar uma mensagem específica.

Quando a biblioteca do gerenciador de recursos recebe uma mensagem, após identifica-la, decide o que fazer com ela com base nas estruturas resmgr_connect_funcs_t e resmgr_io_funcs_t.

A estrutura resmgr_connect_funcs_t é responsável por todas as mensagens de conexão e resmgr_io_funcs_t pelas mensagens de I/O.

Estrutura de atributos usada pelo dispositivo

A estrutura de atributos contém informações sobre nosso dispositivo específico associado ao pathname e as informações sobre permissões, tipo de dispositivo, proprietário e ID do grupo.

Ela descreve os dados e o estado associados a um serviço oferecido por um gerenciador de recursos.

Usamos a função iofunc_attr_init() para inicializar esta estrutura. Destaque para o argumento “modo” (S_IFNAM | 0666) onde definimos o tipo e as permissões de acesso que desejamos usar para o recurso. É necessário restringi-los de acordo com o que se deseja que outros processos e usuários possam fazer com o gerenciador de recursos.

Anexar um nome de caminho (pathname)

O gerenciador de recursos precisa informar aos outros programas (por meio do gerenciador de processos) que ele é o responsável por um prefixo de nome de caminho específico para que possa começar a receber mensagens. Isso é feito através do registro do nome do caminho.

Depois que o gerenciador de recursos estabelece seu nome, ele recebe mensagens quando qualquer programa cliente tenta executar uma operação (por exemplo, open(), close(), read(), write()) nesse nome.

Neste exemplo, /dev/my_device será o nome associado ao dispositivo gerenciado pelo Resource Manager.

Alocar a estrutura do contexto 

A função dispatch_context_alloc() retorna um ponteiro de contexto de despacho que será utilizada a seguir no loop de mensagens.

Iniciar o loop de mensagens do gerenciador de recursos

A partir deste momento o gerenciador permanece em loop manipulando as mensagens que receber, disparando funções callbacks de acordo com seu tipo.

O que ocorre no lado do cliente?

Quando um cliente executa uma função que requer resolução de nome de caminho como em open(), rename(), stat() ou unlink(), mensagens do tipo “connect messages” são enviadas e então cria-se um contexto para esta solicitação.

A biblioteca C do cliente constrói uma mensagem _IO_CONNECT e a envia para o gerenciador de recursos. A mensagem vai ser recebida, decodificada e uma função de manipulação adequada será chamada.

Operações como read() e write() executadas pelo cliente resultam em mensagens _IO_READ e _IO_WRITE respectivamente construídas pela biblioteca C do cliente.

A seguinte figura ilustra o processo de comunicação entre a aplicação cliente, o Resource Manager e o Process Manager.

Figura 1: Troca de mensagens com a aplicação cliente Fonte: QNX Developers

  1. Primeiro o cliente envia uma mensagem ao Process Manager solicitando que ele faça uma busca por um nome de caminho em uma tabela. 
  2. O gerenciador de processos indica quem é o responsável por este nome e retorna o nd, pid , chid e handle que estão associados ao prefixo do nome de caminho.
  3. O cliente envia uma mensagem de conexão (connect message) ao canal do Resource Manager que resulta em um descritor de arquivo (fd).
  4. Uma mensagem de aprovação (como o descritor de arquivos) ou falha é retornada.
  5. A partir de agora, o cliente pode trocar mensagens (I/O messages) com o dispositivo através de operações de leituras e escrita sempre intermediadas pelo Resource Manager.

Um exemplo completo

Agora vamos criar um gerenciador de recursos completo para um dispositivo fictício chamado “counter” onde vamos querer ler e escrever dados nele usando funções de operações básicas de entrada e saída em C.

O único objetivo deste dispositivo é manter o valor de um contador interno que é incrementado à cada leitura realizada por um programa cliente. Seu valor também pode ser alterado a qualquer momento.

Importante ter em mente que o código de exemplo a seguir é completamente funcional, mas será apenas um guia de como implementar um Resouce Manager no QNX.

Consulte a documentação oficial para conhecer como implementar diversas melhorias, otimizações e incluir mecanismos de proteções adicionais.

Observe counter no diretório /dev no console do target QNX após a execução do gerenciador de recursos.

Figura 2: Gerenciador de recursos em execução no Target Fonte: Autor

Para testar o funcionamento, criei um programe cliente bem simples. Ele fará leituras no nosso dispositivo a cada 1 segundo e vai exibir o valor atual do seu contador interno.

Para testar também a escrita no dispositivo, note que após 10 leituras, um novo valor é enviado e então o valor do contador interno é atualizado.

Figura 3: Programa cliente para testar o gerenciador de recursos Fonte: Autor

O resultado é mostrado na figura seguinte.

Figura 4: Resultado da execução (cliente) Fonte: Autor

Conclusão

Neste texto, exploramos o conceito e a implementação de Resource Managers (gerenciadores de recursos) no sistema operacional QNX, destacando suas vantagens e funcionalidades.

Diferente dos sistemas operacionais tradicionais, onde o kernel gerencia diretamente os recursos de hardware, o QNX adota uma abordagem modular e escalável utilizando sua arquitetura microkernel. Nesse modelo, os Resource Managers fornecem uma interface consistente e abstrata para a interação com dispositivos e sistemas de arquivos, permitindo que processos acessem recursos específicos de maneira segura e eficiente através de operações POSIX padrão.

Além disso, vimos exemplos práticos de como interagir com dispositivos gerenciados por Resource Managers, tanto através de programas em C quanto por meio de utilitários de linha de comando.

A documentação oficial do QNX oferece recursos adicionais para aprimorar e otimizar a implementação de Resource Managers, garantindo que desenvolvedores possam criar soluções robustas e adaptáveis para diversas aplicações.

Referências

Aqui estão as referências formatadas de acordo com o estilo APA:

1. QNX Software Systems. (n.d.). Interprocess Communication (IPC) https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.sys_arch/topic/ipc.html 

2. QNX Software Systems. (n.d.). Microkernel architecture.  https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.sys_arch/topic/intro_MICROKERNELARCH.html 

3. QNX Software Systems. (n.d.). Resource Managers.  https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.getting_started/topic/s1_resmgr.html 

4. QNX Software Systems. (n.d.). Why write a resource manager?  https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.sys_arch/topic/resource_WhyWrite.html 

5. QNX Software Systems. (n.d.). Resource manager architecture.  https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.sys_arch/topic/resource_RESMGRARCH.html 

6. QNX Software Systems. (n.d.). Writing a Resource Manager.  https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.resmgr/topic/about.html 

7. QNX Software Systems. (n.d.). Writing a Resource Manager.  https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.getting_started/topic/s1_resmgr_Writing.html 

8. QNX Software Systems. (2020, January 22). Demystifying QNX System programming – Device Resource Management [Video]. YouTube.  https://www.youtube.com/watch?v=x6BO9bx4uvE 

Outros artigos da série

<< Desenvolvimento de IPC no QNX – Fundamentos
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
Inline Feedbacks
View all comments
Home » Software » Desenvolvendo Resource Managers no QNX – Um Guia Prático

EM DESTAQUE

WEBINARS

LEIA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste:


Seminário de
Sistemas Embarcados e IoT 2024
 
Data: 25/06 | Local: Hotel Holiday Inn Anhembi, São Paulo-SP
 
GARANTA SEU INGRESSO

 
close-link