POSIX Semaphore

Esse é o 19º artigo da série Comunicação entre Processos. Nesse artigo é demonstrado o uso do IPC com o padrão POSIX Semaphore.
POSIX Semaphore

POSIX Semaphore é uma padronização desse recurso para que fosse altamente portável entre os sistemas. Não difere tanto da Semaphore System V, é normalmente usado para sincronização de Threads.

Systemcalls

Para utilizar a API referente ao Semaphore é necessário realizar a linkagem com a biblioteca pthread

Esta função cria ou abre um semaphore existente

Esta função incrementa o semaphore, permitindo assim que outro processo ou thread que estejam em estado de wait possa realizar o lock

Essa função decrementa o semaphore apontado pelo descritor.

Fecha o semaphore, permitindo a liberação do recurso alocado para o seu uso

Remove o semaphore imediatamente, o semaphore é destruído quando todos os processos que o utiliza fecha.

Implementação

Para facilitar o uso desse mecanismo, o uso da API referente a POSIX Semaphore é feita através de uma abstração na forma de uma biblioteca.

posix_semaphore.h

Para o seu uso é criado um estrutura que guarda o seu contexto, e o nome do semaphore

As ações pertinentes ao semaphore permitem criar, pegar, liberar, esperar e liberar o recurso.

posix_semaphore.c

Aqui em POSIX_Semaphore_Create criamos o semaphore baseado no nome e seu contexto e guardado em handle.

Na POSIX_Semaphore_Get é verificado se o semaphore está disponível para uso.

Incrementa o semaphore para o habilitar seu uso

Aguarda que o semaphore seja liberado para ser usado

Libera os recursos alocados para o semaphore

Para demonstrar o uso desse IPC, iremos utilizar o modelo Produtor/Consumidor, onde o processo Produtor(button_process) vai escrever seu estado interno no arquivo, e o Consumidor(led_process) vai ler o estado interno e vai aplicar o estado para si. 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 interno no arquivo
  • led_interface – é responsável por ler do arquivo o estado interno do botão 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 do Semaphore, e a interface do botão devidamente preenchida.

button_interface.c

A implementação da interface baseia-se em inicializar o botão, inicializar o Semaphore, e no loop incrementa o semaphore 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 do Semaphore, e a interface do LED devidamente preenchida.

led_interface.c

A implementação da interface baseia-se em inicializar o LED, inicializar o Semaphore, e no loop verifica se há semaphore disponível para poder alterar o seu estado.

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 faciliar 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 do LOG 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.

Matando os processos

Para matar os processos criados execute o script kill_process.sh

Conclusão

POSIX Semaphore é um modo moderno de realizar sincronização entre os acessos às partes críticas do sistema, diferente do Semaphore System V é largamente utilizado para a sincronização de Threads. De qualquer forma é uma alternativa ao Semaphore System V.

Referência

Outros artigos da série

<< POSIX QueuePOSIX Shared Memory >>

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
0 Comentários
Inline Feedbacks
View all comments

WEBINAR

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

DATA: 26/10 ÀS 19:30 H