Shared Memory System V

Esse é o 17º artigo da série Comunicação entre processos. Nesse artigo é apresentado o uso da Shared Memory System V.

Introdução

Em programação Multiprocesso, cada processo(programa em execução) possui sua memória isolada dos demais processos, mas há situações que todos esses processos possuem a mesma base de dados, existem aplicações que não é interessante cada processo possuir uma cópia desses dados, pois o dado está em constante mudança sendo ele um input para todos os processos. Ao invés de enviar o mesmo dado para todos os processos interessados, sendo esses processos residentes no mesmo contexto(computador), existe um recurso chamado de Shared Memory que compartilha um região de memória entre todos os processos. Neste artigo será abordado o uso do IPC Shared Memory System V.

Shared Memory System V

Shared Memory é um bloco de memória alocado pelo processo criador, esse bloco de memória fica acessível por meio de um identificador. Outros processos que quiserem usar essa memória deve se conectar a ela. Todo dado alterado nessa região fica disponível para todos os processos anexados.

Systemcalls

Cria a Shared Memory apartir da chave

Permite conectar um processo a uma Shared Memory

Permite desconectar um processo de uma Shared Memory

Permite controlar os atributos de uma Shared Memory, para remover basta usar o comando IPC_RMID

ipcs

A ferramenta ipcs é um utilitário para poder verificar o estado dos IPC’s sendo eles: Queues, Semaphores e Shared Memory, o seu funcionamento será demonstrado mais a seguir. Para mais informações execute:

Implementação

Para facilitar a implementação a API da Shared Memory foi abstraída para facilitar o uso.

shm.h

Aqui é definido a estrutura para guardar o contexto referente a Shared Memory

Para facilitar o uso da Shared Memory foi criada uma abstração onde o Shared_Memory_Init cria e conecta a uma Shared Memory, Shared_Memory_Detach desconecta o processo da Shared Memory e Shared_Memory_Destroy remove a Shared Memory

shm.c

Aqui a Shared Memory é criada e já conecta o processo

Nessa função o processo é desconectado da Shared Memory

Esta função é responsável por remover a Shared Memory do sistema

Para demonstrar o uso desse IPC, será utilizado o modelo Produtor/Consumidor, onde o processo Produtor(button_process) vai escrever seu estado em uma mensagem, e inserir na queue, e o Consumidor(led_process) vai ler a mensagem da queue e aplicar ao seu estado interno. A aplicação é composta por três executáveis sendo eles:

  • launch_processes – é responsável por lançar os processos button_process e led_process através da combinação fork e exec
  • button_interface – é responsável por ler o GPIO em modo de leitura da Raspberry Pi e escrever o estado em uma mensagem e inserir na queue
  • led_interface – é responsável por ler a mensagem da queue e aplicar em um GPIO configurado como saída

launch_processes.c

No main criamos duas variáveis para armazenar o PID do button_process e do led_process, e mais duas variáveis para armazenar o resultado caso o exec venha a falhar.

Em seguida criamos um processo clone, se processo clone for igual a 0, criamos um array de strings com o nome do programa que será usado pelo exec, em caso o exec retorne, o estado do retorno é capturado e será impresso no stdout e aborta a aplicação. Se o exec for executado com sucesso o programa button_process será carregado.

O mesmo procedimento é repetido novamente, porém com a intenção de carregar o led_process.

button_interface.h

Para usar a interface do botão precisa implementar essas duas callbacks para permitir o seu uso

A assinatura do uso da interface corresponde ao contexto do botão, que depende do modo selecionado, o contexo da Shared Memory, e a interface do botão devidamente preenchida.

button_interface.c

A implementação da interface baseia-se em inicializar o botão, inicializar a Shared Memory, e no loop realiza a escrita na Shared Memory mediante o pressionamento do botão.

led_interface.h

Para realizar o uso da interface de LED é necessário preencher os callbacks que serão utilizados pela implementação da interface, sendo a inicialização e a função que altera o estado do LED.

A assinatura do uso da interface corresponde ao contexto do LED, que depende do modo selecionado, o contexo da Shared Memory, e a interface do LED devidamente preenchida.

led_interface.c

A implementação da interface baseia-se em inicializar o LED, inicializar a Shared Memory, e no loop realiza a leitura do conteúdo da Shared Memory

Compilando, Executando e Matando os processos

Para compilar e testar o projeto é necessário instalar a biblioteca de hardware necessária para resolver as dependências de configuração de GPIO da Raspberry Pi.

Compilando

Para facilitar a execução do exemplo, o exemplo proposto foi criado baseado em uma interface, onde é possível selecionar se usará o hardware da Raspberry Pi 3, ou se a interação com o exemplo vai ser através de input feito por FIFO e o output visualizado através de LOG.

Clonando o projeto

Pra obter uma cópia do projeto execute os comandos a seguir:

Selecionando o modo

Para selecionar o modo devemos passar para o cmake uma variável de ambiente chamada de ARCH, e pode-se passar os seguintes valores, PC ou RASPBERRY, para o caso de PC o exemplo terá sua interface preenchida com os sources presentes na pasta src/platform/pc, que permite a interação com o exemplo através de FIFO e LOG, caso seja RASPBERRY usará os GPIO’s descritos no artigo.

Modo PC

Modo RASPBERRY

Executando

Para executar a aplicação execute o processo launch_processes para lançar os processos button_process e led_process que foram determinados de acordo com o modo selecionado.

Uma vez executado podemos verificar se os processos estão rodando atráves do comando

O output

Interagindo com o exemplo

Dependendo do modo de compilação selecionado a interação com o exemplo acontece de forma diferente

MODO PC

Para o modo PC, precisamos abrir um terminal e monitorar os LOG’s

Dessa forma o terminal irá apresentar somente os LOG’s referente ao exemplo.

Para simular o botão, o processo em modo PC cria uma FIFO para permitir enviar comandos para a aplicação, dessa forma todas as vezes que for enviado o número 0 irá logar no terminal onde foi configurado para o monitoramento, segue o exemplo

Output dos LOG’s quando enviado o comando algumas vezez

MODO RASPBERRY

Para o modo RASPBERRY a cada vez que o botão for pressionado irá alternar o estado do LED.

ipcs funcionamento

Para inspecionar as shared memories presentes é necessário passar o argumento -m que representa queue, o comando fica dessa forma:

O Output gerado na máquina onde o exemplo foi executado, é possível notar que existem outros processos usando Shared Memory.

Sabendo o PID é possível verificar qual processo escreveu e qual processo realizou a última alteração no conteúdo

O output gerado.

Neste caso a saída possui vários resultados. Para conseguir informações sobre o processo em questão é necessário filtrar

O output gerado corresponde ao PID do botão, que alterou o conteúdo.

Matando os processos

Para matar os processos criados execute o script kill_process.sh

Conclusão

Shared Memory é extremamente útil quando se precisa de performance no acesso aos dados, sendo um ótimo recurso para o compartilhamento de dados. Este recurso deve ser usado com muita cautela, se houver mais de um processo alterando os dados é necessário um mecanismo de sincronização(semphores) para que não haja concorrência no acesso às informações. Este é o último IPC do padrão System V. No próximo artigo será abordado o padrão POSIX.

Referência

Outros artigos da série

<< System V – SemaphorePOSIX Queue >>

Engenheiro Elétrico de Formação mas é Engenheiro de Software de profissão, Pós Graduado em Sistemas Embarcados. Apaixonado por Idiomas, mas o idioma que mais lhe fascina é a Linguagem C.
Jogador de CTF, mas prefire Battlefield 1, exige menos da capacidade cognitiva :P. Atualmente atua como desenvolvedor de sistemas distribuídos no ramo aeronáutico. Quando está de bobeira fica desenhando personagens de Anime, criando conteúdo para o canal[Solidcris - Zerando Games] ou pedalando pela cidade de São Paulo.

Notificações
Notificar
guest
2 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Vinicius Mylonas
Membro
27/07/2021 08:58

Estou acompanhando toda a série, parabéns e obrigado por compartilhar.
Tive um professor agora na pós que enfatizou bem, assim como você, a importância da cautela, problemas de concorrência são fáceis de se criar e difíceis de se reproduzir por não serem determinísticos.

WEBINAR

Imagens de Ultrassom: Princípios e Aplicações

DATA: 26/10 ÀS 19:30 H